【问题标题】:How do I implement an Account on Android without a SyncAdapter如何在没有 SyncAdapter 的情况下在 Android 上实现帐户
【发布时间】:2013-07-09 07:04:20
【问题描述】:

我正在使用内置帐户系统(使用 AccountManager API)为 Android 应用程序实现登录系统。

在 Android 2.2+ 上一切正常,但在 Android 2.1 上,不包括 SyncAdapter 会导致帐户设置屏幕重新启动(请参阅 http://code.google.com/p/android/issues/detail?id=5009AccountManager without a SyncAdapter?

为了解决这个问题,我实现了一个存根 SyncAdapter,它只从 IBinder onBind(Intent intent) 返回 null,并将相关内容添加到清单中。这解决了 Android 2.1 上的重启问题。

但是它引入了另一个问题:添加帐户后,Android 系统会在稍后的某个时间启动帐户同步。虽然没有发生错误(实际上我的 SyncAdapter 什么都不做,除非返回null,否则它无法导致错误),同步图标仍然停留在顶部的通知栏中。这会导致 Android 同步系统保持永久唤醒锁定,防止设备进入睡眠状态。

帐户不会在帐户设置屏幕(在“数据和同步”标题下)列出任何可同步的组件,并且始终在帐户列表中显示同步状态的“同步已关闭”(即使同步图标在通知栏中可见)。禁用帐户同步并不能消除问题。删除帐户即可解决问题。

我的猜测是我不应该返回 null。我应该返回 ThreadedSyncAdapter 的基本实现吗?非常感谢任何帮助让没有关联同步的帐户系统在 2.1 和 2.2+ 上正常工作。

【问题讨论】:

    标签: android user-accounts accountmanager android-syncadapter android-wake-lock


    【解决方案1】:

    由于这是我见过的唯一一个与此问题相关的问题,因此这里有 > 年迟到的答案。由于android系统自动同步我的自定义帐户,我还遇到了永久唤醒锁定问题。

    处理此问题的最佳方法,它需要最少的代码,并且实际上使帐户永远不会同步,除非专门调用以在代码中同步:

    ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
    

    现在这要求您在创建帐户时调用此静态方法。而第一个参数是设置此设置的帐户,第二个参数是使用的内容提供者的权限,第三个是整数,当设置为正数时启用同步,设置为 0 时禁用同步,设置为其他任何值让它不为人知。要使用的权限可以在您的 SyncAdapter 使用的 contentAuthority 属性下的“sync_something.xml”中找到:

    <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:contentAuthority="com.android.contacts" 
    android:accountType="com.myapp.account"/> <!-- This being your own account type-->
    

    上面的 xml 文件是在你的 AndroidManifest.xml 的服务部分中指定的:

    <service android:name=".DummySyncAdapterService"
            exported="true"
            android:process=":contacts">
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>
            <meta-data android:name="android.content.SyncAdapter" 
                android:resource="@xml/sync_something" /> <!--This points to your SyncAdapter XML-->
        </service>
    

    这是我用来在我的 LoginActivity 中创建自定义帐户的代码 sn-p:

    Account account = new Account("John Doe", "com.myapp.account");
    ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
    AccountManager am = AccountManager.get(LoginActivity.this);
    boolean accountCreated = am.addAccountExplicitly(account, "Password", null);
    Bundle extras = LoginActivity.this.getIntent().getExtras();
    if(extras != null){
        if (accountCreated) { 
            AccountAuthenticatorResponse response = extras.getParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
            Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ACCOUNT_NAME, "John Doe");
            result.putString(AccountManager.KEY_ACCOUNT_TYPE, "com.myapp.account");
            response.onResult(result);
        }
    }
    

    这很重要的是,当系统尝试同步服务时,它会首先检查服务是否可同步,如果设置为 false,则会取消同步。现在您不必创建自己的ContentProvider,您的ContentProvider 也不会显示在数据和同步下。 但是,您确实需要有一个 AbstractThreadedSyncAdapter 的存根实现,它在其 onBind 方法中返回一个 IBinder。 最后但并非最不重要的一点是,它使用户无法启用同步或使用“立即同步” " 按钮,除非您已在应用中添加了该功能。

    【讨论】:

      【解决方案2】:

      我解决了自己的问题:您不能从服务的 onBind 方法返回 null - 您必须返回 AbstractThreadedSyncAdapterIBinder

      这会在帐户设置页面的“数据和同步”部分添加一个条目,尽管我的 AbstractThreadedSyncAdapter 实现什么也没做;我希望避免这种情况。

      总而言之,要使用 Android 中的帐户系统,您必须:

      • android.content.SyncAdapter 实现一个具有IntentFilter 的服务。
      • 此服务必须从其onBind 方法返回AbstractThreadedSyncAdapter 实现的IBinder
      • 这需要您有一个ContentProvider(可以只是一个存根实现),在您的 SyncAdapter XML 文件中称为 contentAuthority
      • 这有一个缺点,即您的 ContentProvider 列在您帐户设置页面的数据和同步标题下。

      【讨论】:

      • 如果没有人可以建议一种添加帐户的方法没有关联的 SyncAdapter,我将标记为正确答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-29
      • 2017-03-14
      • 1970-01-01
      • 2010-09-10
      • 1970-01-01
      • 2020-04-29
      • 1970-01-01
      相关资源
      最近更新 更多