SecurityException:调用者uid XXXX与authentication者的uid不同
尝试实现Sample Sync Adapter应用程序时,收到上述exception。 我看到很多与这个问题有关的post,但是没有得到满意的答复。
所以我会在这里记下我的解决scheme ,以防其他人遇到同样的问题。
一些其他有用的技巧来debugging这样的问题。
首先启用一些标签的详细日志logging:
$ 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
你会看到这样的日志logging:
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
这意味着没有为此帐户types注册authentication者。 要查看哪些authentication程序已注册,请在安装软件包时观看日志:
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
我有问题的身份validationXML描述符引用一个string资源,在安装过程中没有得到正确解决:
android:accountType="@string/account_type"
日志显示
encountered new type: ServiceInfo: AuthenticatorDescription {type=@2131231194}, ...
用一个普通的string(不是资源)replace它解决了这个问题。 这似乎是Android 2.1的具体。
android:accountType="com.example.account"
首先,检查在这个职位上解释的条件:
[…]如果您从caller uid XXXX is different than the authenticator's uid
的AccountManagerService
中看到错误caller uid XXXX is different than the authenticator's uid
,则可能有点误导。 该消息中的“身份validation器”不是您的身份validation器类,它是Android可以识别的帐户types的注册身份validation器。 在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
。 这是我搞砸的地方。 我用一个常量指定的types创build我的Account
:
class LoginTask { Account account = new Account(userId, AuthenticatorService.ACCOUNT_TYPE); ... } class AuthenticatorService extends Service { public static final String ACCOUNT_TYPE = "com.joelapenna.foursquared"; ... }
但是这个常量与我的validation器的XML定义不匹配:
<account-authenticator xmlns:android="/web/20150729061818/http://schemas.android.com/apk/res/android" android:accountType="com.joelapenna.foursquared.account" ... />
其次,如果你像我一样,想要将样本embedded到现有的应用程序中进行testing,那么请确保使用属于本示例的一部分的Constants
类而不是android.provider.SyncStateContract
包。 因为这两个类都使用创buildAccount
对象时使用的相同属性名称ACCOUNT_TYPE
。
在我的情况下,问题是非常简单地在res/xml/authenticator.xml
声明的android:accountType="com.foo"
的不匹配为android:accountType="com.foo"
但在创build帐户时被错误地称为"foo.com"
Account newAccount = new Account("dummyaccount", "foo.com");
卫生署!
有几个部分来实现自定义帐户…
要在您的活动中调用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相同的string!
<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>
最后,你必须定义你的服务你的清单。 请不要忘记pipe理您的帐户的相关权限(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);
如果您在清单中的意图filter中input了不正确的值,则会出现相同的错误。 我经历了同步适配器上的android-dev教程,并最终为“intent-filter / action android:name”以及“meta-data / android:name”为syncadapter / accountauthenticator设置了一个伪造的值。 这个错误导致了相同的错误出现在日志中。
为了logging,正确的值是:{android.content.SyncAdapter,android.accounts.AccountAuthenticator}
确保您的服务XML指向正确的位置。
例如,如果你是模块名称是
com.example.module.auth
你的服务android:name应该是
<service android:name=".module.auth.name-of-authenticator-service-class"...
在AndriodManifest.xml中
首先,看看Jan Berkel出色的debuggingbuild议。
最后,要检查的另一件事是你的内容提供者和authentication以及同步服务被声明为application
标签的子代。
<application ...> <activity ...(Activity)... </activity> <provider ...(CP service declaration)/> <service ...(Authentication service declaration)... </service> <service ...(Sync service declaration)... </service> </application>
对我来说这是一个非常愚蠢的错误,很难find。
我在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"/>
问题没有了
也,
检查一下,看看你是不是像普通的老string那样对待AccountType。
我有我的大部分代码打包在com.mycompany.android下
我一直使用以下AccountType成功: com.mycompany.android.ACCOUNT 。
现在我有一个使用多个帐户的愿望,当我尝试在帐户末尾附加“.subType”的方法时,
调用者uid xxxxx与authentication者的uid不同
但是,如果我使用“_subType”(下划线而不是点),它工作正常。
我的猜测是,Android正试图将com.mycompany.android.ACCOUNT作为一个合法的软件包名称,而这肯定不是。
所以,再次:
BAD com.mycompany.android.ACCOUNT.subType
好的 com.mycompany.android.ACCOUNT_subType
如果你得到这个错误,以上所有的解决scheme都不适合你。 另外,你认为你已经遵循了所有的程序。 身份validation服务可能是由其他开发人员开发的,您希望使用它来添加帐户。
您可以尝试的是尝试使用发行密钥库对您的应用程序进行签名。 现在你运行该应用程序。 我想这应该适合你。
这是另一个可能的解决scheme。
当我的用户在我的应用程序中注册与他的Android谷歌帐户相同的电子邮件时,我有这个错误。
所以,当我试图accountManager.getAccounts()
和search这个电子邮件时,我发现一个帐户使用相同的电子邮件,但与另一个帐户types。 所以,当试图使用这个(google.com)帐户时,我得到这个错误。
所以,find一个帐户的正确方法是:
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; }
还要确保您的AccountAuthenticatorService具有certificate者意图filter;
即。
<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>
如果在三星设备上出现此exception,请确保您没有使用安全模式 。
如果相同的应用程序来自不同的商店,例如亚马逊应用程序商店和谷歌Play商店,最终的安全性exception将被抛出,因为在这种情况下应用程序的签名将是不同的。如果你计划使用相同的身份validation器login,任一应用程序将崩溃。 我曾经遇到过这个麻烦。 特别是亚马逊的app store会为了安全的目的而用自己的签名来签署它的应用程序。
注意:如果没有input错误或其他答案,请在单点login时检查应用程序的签名。
对于那些仍然遇到问题的人: https ://stackoverflow.com/a/37102317/4171098
在我的情况下,我无意中在
<application>
标签之外的Manifest中定义了AuthenticatorService。 移动<application>
的声明修复了这个问题。 希望会帮助别人。
- 执行失败的任务:在Android Studio中的应用程序:compileDebugJavaWithJavac
- 点击时如何更改Android中button的颜色?
- 如何知道在使用SupportMapFragment时地图已准备好使用?
- Android Studio 1.2.1.1 – 无法find样式“textViewStyle”
- 在Eclipse中更改SDK版本? 无法parsing目标android-x
- BroadcastReceiver.onReceive是否总是在UI线程中运行?
- Android NDK:无法制定目标
- GCM(现在FCM)是否有任何限制?
- 未findSDK位置。 使用sdk.dir在local.properties文件中定义位置,或者使用ANDROID_HOME环境variables定义位置