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

问题描述:

我正在为使用内置帐户系统(使用AccountManager API)的Android应用程序实现登录系统。如何在没有SyncAdapter的情况下在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 +正常工作非常感谢。

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

虽然我的AbstractThreadedSyncAdapter的实现不做任何事情,但这会在帐户设置页面的数据和同步部分中添加条目产生不良影响;我希望避免这种情况。

总之,为了利用账户系统在Android中你必须:

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

如果没有人可以建议添加帐户*,但没有关联的SyncAdapter,则我将标记为正确答案 – 2011-03-21 20:36:34

+0

标记为正确,但输入仍然非常受欢迎。 – 2011-03-29 00:16:27

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

来处理这种情况的最好办法,这需要最少的代码,实际上使得它如此的帐户从未同步,除非特别要求在代码同步:

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

现在,这需要的那一刻您创建帐户你调用这个静态方法。第一个参数是设置此设置的帐户,第二个参数是使用的contentprovider权限,第三个参数是设置为正数时启用同步的整数,当设置为0时禁用同步并设置为其他任何设置使其未知。

<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中的服务部分中规定的是::要使用的权限可以在“sync_something.xml”的contentAuthority属性下,这是由您的SyncAdapter内找到

<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); 
    } 
} 

这个最大的部分是,当SY stem尝试同步服务,它检查服务是否可以先同步,如果设置为false,则取消同步。现在,您不必创建自己的ContentProvider,也不需要在数据和同步下显示ContentProvider但是,您确实需要有一个AbstractThreadedSyncAdapter的存根实现,它在onBind方法内返回一个IBinder。最后但并非最不重要的是,它使得用户无法启用同步功能或使用此帐户的“立即同步”按钮,除非您在应用程序内部添加了功能。

+0

感谢您的输入。 – 2012-11-07 11:28:27