Sample Sync Adapterアプリケーションを実装しようとすると、上記の例外が発生しました。この問題に関連する投稿を多数見ましたが、満足のいく応答はありません。
回答:
このような問題をデバッグするためのその他の役立つヒント。
まず、いくつかのタグの詳細ログを有効にします。
$ 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}, ...
通常の文字列(リソースではない)に置き換えると、問題が解決しました。これはAndroid2.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.xmlとして宣言されandroid:accountType="com.foo"たaccountTypeの不一致でしたが"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と同じ文字列である必要があります。
<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);
マニフェストのインテントフィルターに誤った値を入力した場合も、同じエラーが表示されます。sync-adaptersのandroid-devチュートリアルを実行したところ、syncadapter / accountauthenticatorの「intent-filter / actionandroid:name」と「meta-data / android:name」に偽の値を設定することになりました。この間違いにより、同じエラーがログに表示されました。
レコードの場合、正しい値は次のとおりです。{android.content.SyncAdapter、android.accounts.AccountAuthenticator}
まず、JanBerkelの優れたデバッグアドバイスをもう一度見てください。
最後に、もう1つ確認する必要があるのは、コンテンツプロバイダーと認証、および同期サービスがapplicationタグの子として宣言されていることです。
<application
...>
<activity
...(Activity)...
</activity>
<provider
...(CP service declaration)/>
<service
...(Authentication service declaration)...
</service>
<service
...(Sync service declaration)...
</service>
</application>
私にとってそれは非常にばかげた間違いであり、見つけるのは非常に困難でした。
authenticationator.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」を追加するアプローチを試みたところ、
呼び出し元のuidxxxxxは、オーセンティケーターのuidとは異なります
ただし、「_ subType」(ドットの代わりにアンダースコア)を使用すると、正常に機能します。
私の推測では、Androidは内部のどこかで、com.mycompany.android.ACCOUNTを正当なパッケージ名として処理しようとしていますが、これは間違いなくそうではありません。
だから、再び:
悪いcom.mycompany.android.ACCOUNT.subType
良いcom.mycompany.android.ACCOUNT_subType
これがもう1つの可能な解決策です。
ユーザーが自分のAndroidGoogleアカウントと同じ電子メールでアプリに登録されたときに、このエラーが発生しました。
その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>、問題が 修正されました。希望は誰かを助けるでしょう。