如何在没有SyncAdapter的情况下在Android上实现帐户?

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

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

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

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

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

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

Solutions Collecting From Web of "如何在没有SyncAdapter的情况下在Android上实现帐户?"

由于这是我见过的唯一与这个问题有关的问题,所以这里是一个晚年的答案。 由于android系统自动同步我的自定义帐户,我也遇到了永久性唤醒锁问题。

处理这个问题的最好办法是,只需要最less的代码,实际上就是这样,除非专门调用代码进行同步,否则帐户永远不会同步。

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

现在,这需要您创build您的帐户的那一刻你调用这个静态方法。 而第一个参数是设置此设置的帐户,第二个参数是使用的内容提供者的权限,第三个参数是当设置为正数时启用同步的整数,当设置为0时禁用同步,并设置为其他任何使其未知。 使用权限可以在SyncAdapter使用的contentAuthority属性下的“sync_something.xml”中find:

 <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中创build自定义帐户的代码片段:

 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,则取消同步。 现在,您不必创build自己的ContentProvider也不需要在Data and Synchronization下显示ContentProvider但是你需要有一个存根实现的AbstractThreadedSyncAdapter,它在onBind方法中返回一个IBinder。 最后但并非最不重要的是,除非您在应用程序中添加了function,否则用户无法启用同步function或使用此帐户的“立即同步”button。

我有点解决了我自己的问题:你不能从你的服务的onBind方法返回null – 你必须返回一个AbstractThreadedSyncAdapterIBinder

虽然我的AbstractThreadedSyncAdapter实现不做任何事情,但是在帐户设置页面的“数据和同步”部分中添加条目的效果却不理想。 我希望避免这一点。

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

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