使用Android AccountManager自定义帐户类型

时间:2012-11-07 18:27:23

标签: android android-intent android-service accountmanager

我有一个帐户类型“mypackage.account”和一个内容权限“mypackage”。我有Service提供AbstractAccountAuthenticator的实现,addAccount方法实现如下:

    /**
     * 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" />

我在Service中定义了这个AndroidManifest.xml,如下所示:

<!-- 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>

这就是设置,现在当我希望屏幕上显示我的帐户类型帐户列表以及添加新帐户的操作时,我有添加帐户操作,如下所示:

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次 - 他们是。有人能告诉我我缺少的东西吗?

3 个答案:

答案 0 :(得分: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的设置来确定哪个帐户验证程序响应添加帐户请求。

答案 1 :(得分:1)

我知道这个问题虽然陈旧,但仍然关闭......

Settings.ACTION_ADD_ACCOUNT

Documentation

  

可以通过向一个或多个可同步内容提供商的权限添加额外的EXTRA_AUTHORITIES来限制可添加的帐户类型。 仅向用户提供可与该内容提供商同步的帐户类型

我认为这就是为什么你必须实现一个空的同步适配器。在使用Settings.EXTRA_ACCOUNT_TYPES时,不应该参考文档(我没有像你那样尝试过两个项目,但它在我正在开发的项目中起到了魅力的作用,我不需要同步 - 适配器:

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

答案 2 :(得分: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());