尝试实施Sample Sync Adapter应用程序时收到上述异常。我已经看到许多与此问题相关的帖子,但没有令人满意的答复。
因此,如果有人遇到同样的问题,我将在这里写下我的解决方案。
Answers:
其他一些有用的技巧可以调试这样的问题。
首先为某些标签启用详细日志记录:
$ adb shell setprop log.tag.AccountManagerService VERBOSE
$ adb shell setprop log.tag.Accounts VERBOSE
$ adb shell setprop log.tag.Account VERBOSE
$ adb shell setprop log.tag.PackageManager VERBOSE
您会看到这样的日志记录:
V/AccountManagerService: initiating bind to authenticator type com.example.account
V/Accounts: there is no service connection for com.example.account
V/Accounts: there is no authenticator for com.example.account, bailing out
D/AccountManagerService: bind attempt failed for Session: expectLaunch true, connected false, stats (0/0/0), lifetime 0.002, addAccount, accountType com.example.account, requiredFeatures null
这意味着没有为该帐户类型注册身份验证器。要查看注册了哪些身份验证器,请在安装软件包时查看日志:
D/PackageManager: encountered new type: ServiceInfo: AuthenticatorDescription {type=com.example.account}, ComponentInfo{com.example/com.example.android.AuthenticatorService}, uid 10028
D/PackageManager: notifyListener: AuthenticatorDescription {type=com.example.account} is added
我遇到的问题是,身份验证器xml描述符引用了在安装过程中未正确解析的字符串资源:
android:accountType="@string/account_type"
日志显示
encountered new type: ServiceInfo: AuthenticatorDescription {type=@2131231194}, ...
用普通字符串(而不是资源)替换它可以解决此问题。这似乎是针对Android 2.1的。
android:accountType="com.example.account"
首先,检查此帖子中说明的条件:
[...]如果您从AccountManagerService的表单看到错误caller uid XXXX is different than the authenticator's uid,则可能会引起误解。该消息中的“身份验证者”不是您的身份验证者类,这是Android理解为该帐户类型的注册身份验证者。AccountManagerService看起来像这样的检查:
private void checkCallingUidAgainstAuthenticator(Account account) {
final int uid = Binder.getCallingUid();
if (account == null || !hasAuthenticatorUid(account.type, uid)) {
String msg = "caller uid " + uid + " is different than the authenticator's uid";
Log.w(TAG, msg);
throw new SecurityException(msg);
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid");
}
}
请注意,hasAuthenticatorUid()需要account.type。这是我搞砸的地方。我Account用常量指定的类型创建我的:
class LoginTask {
Account account = new Account(userId, AuthenticatorService.ACCOUNT_TYPE);
...
}
class AuthenticatorService extends Service {
public static final String ACCOUNT_TYPE = "com.joelapenna.foursquared";
...
}
但是此常量与我的身份验证器的XML定义不匹配:
<account-authenticator xmlns:android="/web/20150729061818/http://schemas.android.com/apk/res/android"
android:accountType="com.joelapenna.foursquared.account" ... />
其次,如果您像我一样,并且希望将示例嵌入到现有应用程序中进行测试,那么请确保使用的Constants类是本示例的一部分,而不是包含在android.provider.SyncStateContract包中。因为两个类都使用与ACCOUNT_TYPE创建Account对象时相同的属性名称。
在我的情况下,问题很简单,就是在res/xml/authenticator.xmlas中声明的accountType不匹配,android:accountType="com.foo"但"foo.com"在创建Account时引用不正确:
Account newAccount = new Account("dummyaccount", "foo.com");
h!
实施自定义帐户的部分很少...
要在您的Activity中调用AccountManager,您已经实现了类似的功能...
Account account = new Account(username, ACCESS_TYPE);
AccountManager am = AccountManager.get(this);
Bundle userdata = new Bundle();
userdata.putString("SERVER", "extra");
if (am.addAccountExplicitly(account, password, userdata)) {
Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, username);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCESS_TYPE);
setAccountAuthenticatorResult(result);
}
在res / xml / authenticator.xml中,您必须定义AccountAuthenticator数据(负责Authenticator UID)。ACCESS_TYPE必须与您在此xml中定义的accountType相同的字符串!
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="de.buecherkiste"
android:icon="@drawable/buecher"
android:label="@string/app_name"
android:smallIcon="@drawable/buecher" >
</account-authenticator>
最后,您必须定义清单服务。请不要忘记管理帐户的相关权限(AUTHENTICATE_ACCOUNTS / USE_CREDENTIALS / GET_ACCOUNTS / MANAGE_ACCOUNTS)
<service android:name=".AuthenticationService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
我的错误是假设AccountManager getAccounts()方法返回仅与我的应用程序上下文关联的帐户。我从
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccounts();
至
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Constants.ACCOUNT_TYPE);
首先,再看一看Jan Berkel的出色调试建议。
最后,要检查的另一件事是您的内容提供者和身份验证以及同步服务被声明为application标记的子代。
<application
...>
<activity
...(Activity)...
</activity>
<provider
...(CP service declaration)/>
<service
...(Authentication service declaration)...
</service>
<service
...(Sync service declaration)...
</service>
</application>
对我来说,这是一个非常愚蠢的错误,很难找到。
在authenticator.xml中,我写了
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.myapp"
android:icon="@drawable/ic_launcher"
android:smallIcon="@drawable/ic_launcher"
android:label="@string/app_name"
/>
代替
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.myapp"
android:icon="@drawable/ic_launcher"
android:smallIcon="@drawable/ic_launcher"
android:label="@string/app_name"
/>
这是导致此错误的原因。希望这对某人有帮助!
就我而言,这是我拥有的清单文件中的权限
<uses-permission android:name="ANDROID.PERMISSION.GET_ACCOUNTS"/>
都是大写字母,当我将其更改为
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
问题消失了
也,
检查您是否将AccountType像普通的旧字符串一样对待。
我的大部分代码都打包在com.mycompany.android下
我一直在成功使用以下AccountType:com.mycompany.android.ACCOUNT。
现在,我希望使用多个帐户,并且当我尝试在帐户末尾附加“ .subType”的方法时,由于
呼叫者uid xxxxx与验证者的uid不同
但是,如果我使用“ _subType”(下划线而不是dot),则可以正常工作。
我的猜测是,Android试图将com.mycompany.android.ACCOUNT视为合法的程序包名称,但事实并非如此。
因此,再次:
BAD com.mycompany.android.ACCOUNT.subType
良好com.mycompany.android.ACCOUNT_subType
如果遇到此错误,则以上所有解决方案均不适合您。同样,您假定您已遵循所有过程。身份验证服务可能是由其他开发人员开发的,您想利用它来添加帐户。
您可以尝试使用发布密钥库对应用程序进行签名。现在,您运行该应用程序。我想这应该对您有用。
这是另一种可能的解决方案。
当我的用户使用与他的Android Google帐户相同的电子邮件在我的应用程序中注册时,出现了此错误。
因此,当我尝试accountManager.getAccounts()搜索此电子邮件时,我发现了一个帐户,但该邮件具有与另一帐户类型相同的电子邮件但。因此,当尝试使用此(google.com)帐户时,出现此错误。
因此,找到帐户的正确方法是:
public Account findAccount(String accountName) {
for (Account account : accountManager.getAccounts())
if (TextUtils.equals(account.name, accountName) && TextUtils.equals(account.type, "myservice.com"))
return account;
return null;
}
accountManager.getAccountsByType("myservice.com")。
还要确保您的AccountAuthenticatorService具有证明者意图过滤器;
即。
<service android:name=".service.AccountAuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
对于仍然遇到问题的用户:https ://stackoverflow.com/a/37102317/4171098
就我而言,我不小心在
<application>代码外的清单中定义了AuthenticatorService 。将声明移入内部<application>可解决此问题。希望会帮助某人。