Powyższy wyjątek otrzymałem podczas próby zaimplementowania aplikacji Sample Sync Adapter. Widziałem wiele postów związanych z tym problemem, ale brak satysfakcjonującej odpowiedzi.
Dlatego zanotuję tutaj moje rozwiązanie na wypadek, gdyby ktoś inny wpadł w ten sam problem.
Odpowiedzi:
Kilka innych przydatnych wskazówek dotyczących debugowania takich problemów.
Najpierw włącz szczegółowe rejestrowanie niektórych tagów:
$ 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
Zobaczysz takie rejestrowanie:
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
Co oznacza, że nie ma zarejestrowanego wystawcy uwierzytelnienia dla tego typu konta. Aby zobaczyć, które uwierzytelniacze są zarejestrowane, obejrzyj dziennik podczas instalowania pakietu:
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
Miałem problem polegający na tym, że deskryptor xml elementu uwierzytelniającego odnosił się do zasobu ciągu, który nie został poprawnie rozwiązany podczas instalacji:
android:accountType="@string/account_type"
Dzienniki pokazały
encountered new type: ServiceInfo: AuthenticatorDescription {type=@2131231194}, ...
Zastąpienie go zwykłym ciągiem (nie zasobem) rozwiązało problem. Wydaje się, że jest to specyficzne dla Androida 2.1.
android:accountType="com.example.account"
źródło
Najpierw sprawdź stan wyjaśniony w tym poście :
[…] Jeśli widzisz błąd
AccountManagerService
w formularzucaller uid XXXX is different than the authenticator's uid
, może to być trochę mylące. „Authenticator” w tej wiadomości nie jest twoją klasą uwierzytelniającą, to jest to, co Android rozumie jako zarejestrowany autentykator dla typu konta. Sprawdzenie, które ma miejsce w ramachAccountManagerService
wygląda następująco: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"); } }
Zauważ, że
hasAuthenticatorUid()
zajmujeaccount.type
. Tutaj schrzaniłem sprawę. Tworzyłem mojeAccount
z typem określonym przez stałą:class LoginTask { Account account = new Account(userId, AuthenticatorService.ACCOUNT_TYPE); ... } class AuthenticatorService extends Service { public static final String ACCOUNT_TYPE = "com.joelapenna.foursquared"; ... }
ale ta stała nie pasuje do definicji XML mojego wystawcy uwierzytelnienia:
<account-authenticator xmlns:android="/web/20150729061818/http://schemas.android.com/apk/res/android" android:accountType="com.joelapenna.foursquared.account" ... />
Po drugie, jeśli jesteś podobny do mnie i chcesz osadzić próbkę w istniejącej aplikacji w celu przetestowania, upewnij się, że używasz
Constants
klasy, która jest częścią tego przykładu, a nie wandroid.provider.SyncStateContract
pakiecie. Ponieważ obie klasy używają tej samej nazwy atrybutu,ACCOUNT_TYPE
która jest używana podczas tworzeniaAccount
obiektu.źródło
W moim przypadku problemem była po prostu niezgodność w accountType zadeklarowanym
res/xml/authenticator.xml
jako,android:accountType="com.foo"
ale przywoływanym nieprawidłowo, jak"foo.com"
podczas tworzenia konta:Account newAccount = new Account("dummyaccount", "foo.com");
No!
źródło
Jest kilka części do wdrożenia konta niestandardowego ...
Aby wywołać AccountManagera w swoim działaniu, coś takiego, jak już zaimplementowałeś ...
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); }
W res / xml / autentikator.xml musisz zdefiniować swoje dane AccountAuthenticator (odpowiedzialne za Twój identyfikator UID Authenticatora). ACCESS_TYPE musi być tym samym ciągiem, co zdefiniowany typ konta w tym XML!
<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>
Wreszcie musisz zdefiniować swoją usługę jako Manifest. Nie zapomnij o odpowiednich uprawnieniach do zarządzania swoimi kontami (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>
źródło
Mój błąd polegał na założeniu, że metoda AccountManager getAccounts () zwróciła tylko konta powiązane z kontekstem mojej aplikacji. Zmieniłem się z
do
źródło
Ten sam błąd pojawi się, jeśli umieścisz nieprawidłowe wartości w filtrach intencji w swoim manifeście. Przeszedłem przez samouczek android-dev na temat adapterów synchronizacji i ostatecznie ustawiłem fałszywą wartość dla „intent-filter / action android: name” oraz „meta-data / android: name” dla syncadapter / accountauthenticator. Ten błąd spowodował pojawienie się tych samych błędów w dziennikach.
Dla rekordu prawidłowe wartości to: {android.content.SyncAdapter, android.accounts.AccountAuthenticator}
źródło
Upewnij się, że kod XML usługi wskazuje poprawną lokalizację.
Na przykład, jeśli nazwa modułu to
jesteś serwisem android: nazwa powinna być
<service android:name=".module.auth.name-of-authenticator-service-class"...
w AndriodManifest.xml
źródło
Po pierwsze, spójrz jeszcze raz na doskonałe rady dotyczące debugowania Jana Berkela.
Na koniec kolejną rzeczą do sprawdzenia jest to, że dostawca treści oraz usługi uwierzytelniania i synchronizacji są zadeklarowane jako elementy
application
podrzędne tagu.<application ...> <activity ...(Activity)... </activity> <provider ...(CP service declaration)/> <service ...(Authentication service declaration)... </service> <service ...(Sync service declaration)... </service> </application>
źródło
Dla mnie był to bardzo głupi błąd i bardzo trudno go było znaleźć.
Napisałem w pliku 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" />
zamiast
<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" />
który powodował ten błąd. Mam nadzieję, że to komuś pomoże!
źródło
W moim przypadku były to uprawnienia w pliku manifestu
<uses-permission android:name="ANDROID.PERMISSION.GET_ACCOUNTS"/>
to były czapki, kiedy zmieniłem to na
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
problem zniknął
źródło
Również,
Sprawdź, czy nie traktujesz AccountType zbyt podobnie jak zwykłego starego ciągu.
Większość mojego kodu jest spakowana pod adresem com.mycompany.android
Z powodzeniem używam następującego AccountType: com.mycompany.android.ACCOUNT .
Teraz chcę używać wielu kont, a kiedy próbuję dodać „.subType” na końcu mojego konta, kończy się to niepowodzeniem.
Jeśli jednak użyję „_subType” (podkreślenie zamiast kropki), działa dobrze.
Domyślam się, że gdzieś pod maską Android próbuje traktować com.mycompany.android.ACCOUNT jako legalną nazwę pakietu, czym z pewnością nie jest.
Więc znowu:
BAD com.mycompany.android.ACCOUNT.subType
DOBRY com.mycompany.android.ACCOUNT_subType
źródło
Jeśli otrzymujesz ten błąd, a wszystkie powyższe rozwiązania nie działają dla Ciebie. Zakładasz również, że wykonałeś całą procedurę. Może się zdarzyć, że usługa uwierzytelniania została opracowana przez innego programistę, z którego chcesz korzystać w celu dodawania kont.
Możesz spróbować podpisać swoją aplikację za pomocą magazynu kluczy wydania. Teraz uruchom aplikację. Przypuszczam, że to powinno działać dla Ciebie.
źródło
Oto kolejne możliwe rozwiązanie.
Wystąpił ten błąd, gdy mój użytkownik był zarejestrowany w mojej aplikacji przy użyciu tego samego adresu e-mail, co jego konto Google na Androida.
Tak więc, kiedy próbowałem
accountManager.getAccounts()
znaleźć ten e-mail, znalazłem konto z tym samym adresem e-mail, ALE z innym typem konta. Tak więc podczas próby użycia tego konta (google.com) pojawia się ten błąd.Tak więc właściwy sposób na znalezienie konta to:
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; }
źródło
accountManager.getAccountsByType("myservice.com")
tego możesz zadzwonić .Upewnij się również, że usługa AccountAuthenticatorService ma filtry intencji dowodu;
to znaczy.
<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>
źródło
Jeśli dostaniesz ten wyjątek na urządzeniach Samsung, upewnij się, że nie używasz trybu awaryjnego .
źródło
Jeśli te same aplikacje pochodzą z innego sklepu, na przykład sklepu z aplikacjami amazon i sklepu Google Play, ostatecznie zostanie wyrzucony wyjątek bezpieczeństwa, ponieważ podpis aplikacji będzie inny w tym przypadku. Zaloguj się, każda z aplikacji ulegnie awarii. raz napotkałem ten problem. Zwłaszcza sklep z aplikacjami amazon podpisywałby swoje aplikacje własnym podpisem ze względów bezpieczeństwa.
Uwaga: jeśli nie ma błędu literowego lub innych odpowiedzi wymienionych tutaj, sprawdź podpis aplikacji w przypadku pojedynczego logowania.
źródło
Dla tych, którzy wciąż doświadczają problemu: https://stackoverflow.com/a/37102317/4171098
źródło