9

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

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

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

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

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

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

4

2 回答 2

6

由于这是我见过的与此问题相关的唯一问题,因此这里有 > 年迟到的答案。由于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 中创建自定义帐户的代码片段:

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。最后但并非最不重要的一点是,除非您在应用程序中添加了该功能,否则用户无法为此帐户启用同步或使用“立即同步”按钮。

于 2012-11-07T09:19:37.897 回答
2

我解决了我自己的问题:你不能nullonBind你的服务方法返回 - 你必须返回IBinder一个AbstractThreadedSyncAdapter.

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

总而言之,为了在 Android 中使用帐户系统,您必须:

  • 实现一个具有IntentFilterfor的服务android.content.SyncAdapter
  • 该服务必须从它的方法返回IBinder一个实现。AbstractThreadedSyncAdapteronBind
  • 这需要您有一个(可以只是一个存根实现),它在您的 SyncAdapter XML 文件ContentProvider中被称为。contentAuthority
  • 不利的一面是,您的 ContentProvider 列在帐户设置页面的数据和同步标题下。
于 2011-03-21T20:35:43.170 回答