2

我有一个帐户类型“mypackage.account”和一个内容授权“mypackage”。我有一个Service提供 的实现AbstractAccountAuthenticatoraddAccount方法是这样实现的:

    /**
     * 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 次,两个应用程序定义的权限是不同的——而且确实如此。有人可以告诉我我缺少什么吗?

4

3 回答 3

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来确定哪个帐户身份验证器响应添加帐户请求。

于 2012-11-07T19:26:17.227 回答
1

我知道这个问题已经过时并且已经关闭了......

文档Settings.ACTION_ADD_ACCOUNT:_

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

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

intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, new String[] { "mypackage.account" });
于 2015-08-05T12:08:29.283 回答
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());
于 2013-10-19T23:49:20.643 回答