我在尝试实现Sample Sync Adapter应用程序时收到了上述异常。我看过很多与此问题相关的帖子,但没有令人满意的答复。
所以我会在这里记下my solution,以防其他人遇到同样的问题。
答案 0 :(得分:54)
调试此类问题的一些其他有用技巧。
首先为某些标记启用详细日志记录:
$ 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
我遇到的问题是authenticator xml描述符引用了一个在安装过程中没有得到正确解析的字符串资源:
android:accountType="@string/account_type"
日志显示
encountered new type: ServiceInfo: AuthenticatorDescription {type=@2131231194}, ...
用普通字符串(不是资源)替换它解决了这个问题。这似乎是Android 2.1特有的。
android:accountType="com.example.account"
答案 1 :(得分:43)
首先,检查this post上解释的条件:
[...]如果您发现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
。
答案 2 :(得分:24)
在我的情况下,问题很简单,在res/xml/authenticator.xml
中声明为android:accountType="com.foo"
的帐户类型不匹配,但在创建帐户时错误地引用为"foo.com"
:
Account newAccount = new Account("dummyaccount", "foo.com");
卫生署!
答案 3 :(得分:10)
实现自定义帐户的部分很少......
在您的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数据(负责您的身份验证器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>
最后,您必须定义您的Manifest服务。请不要忘记管理帐户的相关权限(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>
答案 4 :(得分:5)
我的错误是假设AccountManager getAccounts()方法返回的帐户只与我的应用程序上下文相关联。我改变了
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccounts();
到
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Constants.ACCOUNT_TYPE);
答案 5 :(得分:4)
如果在清单中的intent-filters中放入了不正确的值,则会出现相同的错误。 我经历了关于同步适配器的android-dev教程,并最终设置了“intent-filter / action android:name”的伪造值以及syncadapter / accountauthenticator的“meta-data / android:name”。这个错误导致相同的错误出现在日志中。
对于记录,正确的值为:{android.content.SyncAdapter,android.accounts.AccountAuthenticator}
答案 6 :(得分:2)
确保您的服务XML指向正确的位置。
例如,如果您的模块名称是
com.example.module.auth
你是服务android:name应该是
<service android:name=".module.auth.name-of-authenticator-service-class"...
在AndriodManifest.xml中
答案 7 :(得分:2)
首先,再看看Jan Berkel的优秀调试建议。
最后,要检查的另一件事是您的内容提供商以及身份验证和同步服务被声明为application
标记的子级。
<application
...>
<activity
...(Activity)...
</activity>
<provider
...(CP service declaration)/>
<service
...(Authentication service declaration)...
</service>
<service
...(Sync service declaration)...
</service>
</application>
答案 8 :(得分:2)
对我来说,这是一个非常愚蠢的错误,很难找到。
在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"
/>
导致此错误。希望这有助于某人!
答案 9 :(得分:2)
在我的情况下,它是清单文件中的权限
<uses-permission android:name="ANDROID.PERMISSION.GET_ACCOUNTS"/>
当我把它改为
时,它全部都是上限<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
问题消失了
答案 10 :(得分:1)
此外,
检查您是否将AccountType视为普通旧字符串。
我的大部分代码都打包在 com.mycompany.android
下我成功使用以下AccountType: com.mycompany.android.ACCOUNT 。
现在我想要使用多个帐户,当我尝试在帐户末尾附加“.subType”的方法时,它会失败并带有
调用者uid xxxxx与身份验证者的uid不同
但是,如果我使用“_subType”(下划线而不是点),它可以正常工作。
我的猜测是,在Android的某个地方,Android正试图将com.mycompany.android.ACCOUNT视为合法的包名,但肯定不是。
所以,再次:
BAD com.mycompany.android.ACCOUNT.subType
GOOD com.mycompany.android.ACCOUNT_subType
答案 11 :(得分:1)
如果您收到此错误,并且上述所有解决方案都不适合您。此外,您假设您已遵循所有程序。验证服务可能是由您希望用于添加帐户的其他开发人员开发的。
您可以尝试尝试使用版本密钥库对应用程序进行签名。现在运行该应用程序。我认为这对你有用。
答案 12 :(得分:1)
这是另一种可能的解决方案。
当我的用户在我的应用中使用与他的Android谷歌帐户相同的电子邮件注册时,我遇到此错误。
因此,当我尝试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;
}
并搜索此电子邮件时,我发现一个帐户使用相同的电子邮件但另一种帐户类型。因此,在尝试使用此(google.com)帐户时,我收到此错误。
因此,找到帐户的正确方法是:
SQLite
答案 13 :(得分:0)
还要确保您的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>
答案 14 :(得分:0)
如果您在三星设备上遇到此例外,请确保您没有使用safe mode。
答案 15 :(得分:0)
如果相同的应用程序来自不同的商店,例如亚马逊应用程序商店和谷歌游戏商店,最终将会抛出安全例外,因为在这种情况下应用程序的签名会有所不同。如果您计划使用相同的身份验证器单点登录的目的,任何一个应用程序都会崩溃。我曾经遇到过这个麻烦。特别是亚马逊应用程序商店会为了安全起见,使用自己的签名对其应用程序进行签名。
注意:如果此处未提及拼写错误或其他答案,请在单点登录时检查应用程序的签名。
答案 16 :(得分:0)
对于仍然有问题的人:https://stackoverflow.com/a/37102317/4171098
在我的情况下,我意外地在Manifest中定义了AuthenticatorService 在
<application>
标记之外。将声明移到里面<application>
解决了这个问题。希望会帮助别人。