ฉันได้รับข้อยกเว้นข้างต้นเมื่อพยายามใช้แอปพลิเคชัน Sample Sync Adapter ฉันเห็นโพสต์มากมายที่เกี่ยวข้องกับปัญหานี้ แต่ไม่มีคำตอบที่น่าพอใจ
ดังนั้นฉันจะจดวิธีแก้ปัญหาไว้ที่นี่เผื่อว่าจะมีใครเจอปัญหาเดียวกัน
ฉันได้รับข้อยกเว้นข้างต้นเมื่อพยายามใช้แอปพลิเคชัน 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}, ...
การแทนที่ด้วยสตริงปกติ (ไม่ใช่ทรัพยากร) ช่วยแก้ปัญหาได้ ดูเหมือนว่าจะเป็นเฉพาะ 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 ต้องเป็นสตริงเดียวกับ accountType ที่คุณกำหนดไว้ใน 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>
สุดท้ายคุณต้องกำหนดบริการของคุณ Manifest ของคุณ โปรดอย่าลืมสิทธิ์ที่เกี่ยวข้องในการจัดการบัญชีของคุณ (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);
ข้อผิดพลาดเดียวกันนี้จะปรากฏขึ้นหากคุณใส่ค่าที่ไม่ถูกต้องในตัวกรองความตั้งใจในรายการของคุณ ฉันอ่านบทช่วยสอน android-dev เกี่ยวกับอะแดปเตอร์ซิงค์และลงเอยด้วยการตั้งค่าปลอมสำหรับ "ตัวกรองเจตนา / การดำเนินการ android: name" รวมถึง "meta-data / android: name" สำหรับ syncadapter / accountauthenticator ข้อผิดพลาดนี้ทำให้ข้อผิดพลาดเดียวกันปรากฏในบันทึก
สำหรับเรกคอร์ดค่าที่ถูกต้องคือ: {android.content.SyncAdapter, android.accounts.AccountAuthenticator}
ตรวจสอบให้แน่ใจว่า XML บริการของคุณชี้ไปยังตำแหน่งที่ถูกต้อง
ตัวอย่างเช่นหากคุณชื่อโมดูลคือ
com.example.module.auth
คุณเป็นผู้ให้บริการ android: ชื่อควรเป็น
<service android:name=".module.auth.name-of-authenticator-service-class"...
ใน AndriodManifest.xml
ก่อนอื่นให้ดูคำแนะนำในการแก้ไขข้อบกพร่องที่ยอดเยี่ยมของ 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"
/>
ซึ่งทำให้เกิดข้อผิดพลาดนี้ หวังว่านี่จะช่วยใครสักคน!
ในกรณีของฉันมันเป็นสิทธิ์ในไฟล์รายการที่ฉันมี
<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" ที่ส่วนท้ายของบัญชีของฉันมันล้มเหลวด้วย
ผู้โทร uid xxxxx แตกต่างจาก uid ของผู้รับรองความถูกต้อง
อย่างไรก็ตามหากฉันใช้ "_subType" (ขีดล่างแทนจุด) ก็ใช้ได้ดี
ฉันเดาว่ามีบางแห่งที่อยู่ภายใต้ประทุน Android พยายามที่จะถือว่า com.mycompany.android.ACCOUNT เป็นชื่อแพ็คเกจตามกฎหมายซึ่งแน่นอนว่าไม่
ดังนั้นอีกครั้ง:
BAD com.mycompany.android.ACCOUNT.subType
ดี com.mycompany.android.ACCOUNT_subType
หากคุณได้รับข้อผิดพลาดนี้และวิธีแก้ไขปัญหาข้างต้นทั้งหมดไม่ได้ผลสำหรับคุณ นอกจากนี้คุณถือว่าคุณได้ทำตามขั้นตอนทั้งหมดแล้ว อาจมีความเป็นไปได้ที่บริการตรวจสอบความถูกต้องได้รับการพัฒนาโดยนักพัฒนารายอื่นซึ่งคุณต้องการใช้เพื่อเพิ่มบัญชี
สิ่งที่คุณสามารถลองทำได้คือลองลงนามแอปพลิเคชันของคุณด้วยที่เก็บคีย์รุ่น ตอนนี้คุณเรียกใช้แอปพลิเคชัน ฉันคิดว่าสิ่งนี้น่าจะเหมาะกับคุณ
นี่เป็นอีกวิธีหนึ่งที่เป็นไปได้
ฉันมีข้อผิดพลาดนี้เมื่อผู้ใช้ของฉันลงทะเบียนในแอพของฉันด้วยอีเมลเดียวกันกับบัญชี Google Android ของเขา
ดังนั้นเมื่อฉันพยายาม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>
หากแอพเดียวกันมาจากร้านค้าอื่นเช่น amazon app store และ google play store ในที่สุดข้อยกเว้นด้านความปลอดภัยจะถูกโยนทิ้งเนื่องจากลายเซ็นของแอพจะแตกต่างกันในกรณีนี้หากคุณวางแผนที่จะใช้ตัวตรวจสอบสิทธิ์เดียวกันเพื่อจุดประสงค์เดียว ลงชื่อเข้าใช้แอปใดแอปหนึ่งอาจขัดข้อง ฉันเคยพบปัญหานี้มาแล้วครั้งหนึ่ง โดยเฉพาะอย่างยิ่ง amazon app store จะลงนามแอปด้วยลายเซ็นของตัวเองเพื่อความปลอดภัย
หมายเหตุ: หากไม่มีข้อผิดพลาดในการพิมพ์ผิดหรือคำตอบอื่น ๆ ที่กล่าวถึงที่นี่โปรดตรวจสอบลายเซ็นของแอปในกรณีที่ลงชื่อเข้าใช้เพียงครั้งเดียว
สำหรับผู้ที่ยังคงมีปัญหาหมดอายุ: https://stackoverflow.com/a/37102317/4171098
ในกรณีของฉันฉันกำหนด AuthenticatorService โดยไม่ได้ตั้งใจใน Manifest นอก
<application>แท็ก การย้ายคำประกาศภายใน<application>แก้ไขปัญหาได้ ความหวังจะช่วยใครสักคน