Paul Paul - 22 days ago 10
Android Question

SecurityException: caller uid XXXX is different than the authenticator's uid

I received the above exception when trying to implement Sample Sync Adapter application. I have seen numerous posts related to this issue but no satisfactory response.

So I will jot down my solution here in case anyone else gets into the same issue.

Answer Source

First, check the condition explained on this post:

[...] If you see an error from the AccountManagerService of the form caller uid XXXX is different than the authenticator's uid, it might be a bit misleading. The ‘authenticator’ in that message is not your authenticator class, it’s what Android understands to be the registered authenticator for the account’s type. The check that happens within the AccountManagerService looks like this:

 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");
     }
 }

Note that hasAuthenticatorUid() takes the account.type. This is where I’d screwed up. I was creating my Account with a type specified by a constant:

 class LoginTask {
     Account account = new Account(userId, AuthenticatorService.ACCOUNT_TYPE);
     ...
 }

 class AuthenticatorService extends Service {
     public static final String ACCOUNT_TYPE = "com.joelapenna.foursquared";
     ...
 }

but this constant did not match the XML definition for my authenticator:

 <account-authenticator xmlns:android="/web/20150729061818/http://schemas.android.com/apk/res/android"
        android:accountType="com.joelapenna.foursquared.account" ... />

Second, if you are like me and want to embed the sample into your existing app for testing then, make sure you use Constants class that is part of this example and not under android.provider.SyncStateContract package. Because both classes use the same attribute name ACCOUNT_TYPE that is used when creating Account object.