2012-11-07 28 views
2

我有一個帳戶類型「mypackage.account」和一個內容管理「mypackage」。我有一個Service,其提供的AbstractAccountAuthenticator一個實施方式中,addAccount方法被實現這樣的:使用Android AccountManager的自定義帳戶類型

/** 
    * The user has requested to add a new account to the system. We return an intent that will launch our login 
    * screen if the user has not logged in yet, otherwise our activity will just pass the user's credentials on to 
    * the account manager. 
    */ 
    @Override 
    public Bundle addAccount(AccountAuthenticatorResponse response, String account_type, String auth_token_type, 
          String[] required_features, Bundle options) throws NetworkErrorException { 
     final Intent intent = new Intent(_context, ConnectAccountActivity.class); 
     intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); 
     final Bundle reply = new Bundle(); 
     reply.putParcelable(AccountManager.KEY_INTENT, intent); 

     return reply; 
    } 

我提供一種authenticator.xml

<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" 
        android:accountType="mypackage.account" 
        android:icon="@drawable/ic_launcher" 
        android:smallIcon="@drawable/ic_launcher" 
        android:label="@string/app_name" 
        android:accountPreferences="@xml/account_preferences" /> 

和我在AndroidManifest.xml定義該Service這樣的:

<!-- Account authentication service that provides the methods for authenticating KeepandShare accounts to the 
    AccountManager framework --> 
<service android:exported="true" android:name=".authenticator.AccountAuthenticatorService" android:process=":auth" tools:ignore="ExportedService"> 
    <intent-filter> 
     <action android:name="android.accounts.AccountAuthenticator"/> 
    </intent-filter> 
    <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator"/> 
</service> 

這就是設置,現在當我想要一個屏幕機智^ h我的帳戶類型的帳戶列表在設備上與動作添加一個新的帳戶,我已經添加帳戶的行動看起來像這樣:

final Intent intent = new Intent(Settings.ACTION_ADD_ACCOUNT); 
intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[]{ "mypackage" }); 
startActivity(intent); 

在這一點上,我帶領到一個帳戶類型選擇器顯示「mypackage.account」和「anotherpackage.account」作爲選項。 (「anotherpackage.account」在我工作的另一個應用程序中定義)這似乎不像預期的行爲。我查了大約20次,這兩個應用定義的權限是不同的 - 他們是。有人能告訴我我錯過了什麼嗎?

回答

2

Android解耦來咬我。看來,需要雙方應用程序也有一個sync_adapter.xml,如:

<!-- The attributes in this XML file provide configuration information for the SyncAdapter. --> 
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" 
      android:contentAuthority="mypackage" 
      android:accountType="mypackage.account" 
      android:supportsUploading="true" 
      android:userVisible="true" 
      android:allowParallelSyncs="false" 
      android:isAlwaysSyncable="true"/> 

,並連接到同步服務於AndroidManifest.xml

<!-- Data sync service that provides the SyncAdapter to the SyncManager framework. The SyncAdapter is used to 
    maintain that the set of data on the device is a subset of the data on the server --> 
<service android:exported="true" android:name=".data.sync.SyncService" tools:ignore="ExportedService"> 
    <intent-filter> 
     <action android:name="android.content.SyncAdapter"/> 
    </intent-filter> 
    <meta-data android:name="android.content.SyncAdapter" android:resource="@xml/sync_adapter"/> 
</service> 

爲了完整起見,我Service執行如下:

/** 
* Service that provides sync functionality to the SyncManager through the {@link SyncAdapter}. 
*/ 
public class SyncService extends Service { 

    @Override 
    public void onCreate() { 
     synchronized (_sync_adapter_lock) { 
      if (_sync_adapter == null) 
       _sync_adapter = new SyncAdapter(getApplicationContext(), false); 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return _sync_adapter.getSyncAdapterBinder(); 
    } 

    private static final Object _sync_adapter_lock = new Object(); 
    private static SyncAdapter _sync_adapter = null; 
} 

SyncAdapter

/** 
* Sync adapter for KeepandShare data. 
*/ 
public class SyncAdapter extends AbstractThreadedSyncAdapter { 

    public SyncAdapter(Context context, boolean should_auto_initialize) { 
     super(context, should_auto_initialize); 

     //noinspection ConstantConditions,PointlessBooleanExpression 
     if (!BuildConfig.DEBUG) { 
      Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
       @Override 
       public void uncaughtException(Thread thread, Throwable throwable) { 
        Log.e("Uncaught sync exception, suppressing UI in release build.", throwable); 
       } 
      }); 
     } 
    } 

    @Override 
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, 
           SyncResult sync_result) { 
     // TODO: implement sync 
    } 
} 

即使我實際上沒有任何同步數據(應用程序甚至沒有鏈接到任何服務器現在),Android框架似乎使用SyncAdapter的設置,以找出哪些帳戶身份驗證響應到添加帳戶請求。

+0

這是一個非常全面和有用的答案這個問題。我已經在SDK的「SampleSyncAdaptor」示例中添加了帳戶管理功能,雖然它在點擊「添加帳戶」時跳轉到了我的應用,但添加的帳戶不會顯示在手機設置中。我添加了Dandre的代碼和賓果 - 它的工作原理。不過請注意「Ln」 - 你不需要使用roboguice來完成這項工作 - 可能應該從代碼中刪除。 –

+0

@TimT感謝您的評論。我實際上是從Roboguice中撕下了'Ln',我個人使用Dagger。看起來我只在這裏使用'Ln',所以我會編輯它以使用'Log'。 –

+0

似乎很奇怪,即使您沒有使用同步適配器,也需要添加同步適配器。 嘗試按照此帖子上的說明創建您自己的身份驗證器,然後查看問題是否仍然存在: http://udinic.wordpress.com/2013/04/24/write-your-own-android-authenticator – Udinic

0

而不是調用的意圖......

final Intent intent = new Intent(Settings.ACTION_ADD_ACCOUNT); 
intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[]{ "mypackage" }); 
startActivity(intent); 

您可以使用下面的方法直接進入給帳戶類型的認證過程。這會不是要求你有一個SyncAdapter

AccountManager accountManager = AccountManager.get(this); 
accountManager.addAccount(AccountAuthenticator.ACCOUNT_TYPE, AccountAuthenticator.AUTHTOKEN_TYPE_FULL_ACCESS, null, null, this, new AccountManagerCallback<Bundle>() { 
     @Override 
     public void run(AccountManagerFuture<Bundle> future) { 

     } 
}, new Handler()); 
1

我知道這個問題是舊的,但收...

Settings.ACTION_ADD_ACCOUNTDocumentation

可添加的帳戶類型,可以通過添加額外的EXTRA_AUTHORITIES的意圖被限制與一個或多個可同步內容提供商的權限。只有可以與該內容提供商同步的帳戶類型纔會提供給用戶。

我認爲這就是爲什麼你必須實現一個空的同步適配器。參考文檔,當使用Settings.EXTRA_ACCOUNT_TYPES時,這應該不是必需的(我沒有像你這樣爲兩個項目嘗試它,但它在我目前正在開發的一個項目中的魅力,我根本不需要同步適配器) :

intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, new String[] { "mypackage.account" }); 
相關問題