샘플 동기화 어댑터 애플리케이션을 구현하려고 할 때 위의 예외를 수신했습니다. 이 문제와 관련된 많은 게시물을 보았지만 만족스러운 답변이 없습니다.
그래서 다른 사람이 같은 문제에 빠질 경우를 대비하여 여기에 내 솔루션 을 적어 두겠습니다 .
답변:
이와 같은 문제를 디버깅하기위한 다른 유용한 팁.
먼저 일부 태그에 대해 자세한 로깅을 활성화합니다.
$ 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.
내 경우에는 문제는 단순히 ACCOUNTTYPE의 불일치에 선언 매우이었다 res/xml/authenticator.xml로 android:accountType="com.foo"하지만, 같은 잘못 참조 "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에 대한 "meta-data / android : name"뿐만 아니라 "intent-filter / action android : name"에 대한 가짜 값을 설정했습니다. 이 실수로 인해 로그에 동일한 오류가 나타납니다.
레코드의 경우 올바른 값은 {android.content.SyncAdapter, android.accounts.AccountAuthenticator}입니다.
먼저 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"
/>
이 오류가 발생했습니다. 이것이 누군가를 돕기를 바랍니다!
또한,
AccountType을 일반 문자열처럼 너무 많이 취급하고 있는지 확인하십시오.
대부분의 코드는 com.mycompany.android 아래에 패키징되어 있습니다.
다음 AccountType을 성공적으로 사용하고 있습니다. com.mycompany.android.ACCOUNT .
이제 여러 계정을 사용하고 싶은데 계정 끝에 ".subType"을 추가하는 방법을 시도하면 실패합니다.
발신자 uid xxxxx가 인증 자의 uid와 다릅니다.
그러나 "_subType"(점 대신 밑줄)을 사용하면 제대로 작동합니다.
내 생각 엔 Android가 com.mycompany.android.ACCOUNT를 합법적 인 패키지 이름으로 취급하려고 시도하고 있는데, 이는 확실히 그렇지 않습니다.
그래서 다시 :
BAD com.mycompany.android.ACCOUNT.subType
GOOD 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>태그 외부의 Manifest에서 실수로 AuthenticatorService를 정의했습니다 . 선언을 내부로 이동하면<application>문제가 해결되었습니다. 희망은 누군가를 도울 것입니다.