SecurityException на AccountManager.addAccountExplicitly() для общего модуля Android
Я следил за Android Создание адаптера синхронизации (BasicSyncAdapter), чтобы начать свою собственную логику службы синхронизации.
Проблема: при вызове AccountManager.addAccountExplicitly()
, SecurityException
возникает из-за несоответствия между UID вызывающего абонента и аутентификатора:
java.lang.SecurityException: caller uid 10048 is different than the authenticator's uid
at android.os.Parcel.readException(Parcel.java:1425)
at android.os.Parcel.readException(Parcel.java:1379)
at android.accounts.IAccountManager$Stub$Proxy.addAccount(IAccountManager.java:580)
at android.accounts.AccountManager.addAccountExplicitly(AccountManager.java:565)
Структура приложения / библиотеки: Мое приложение разделено на два модуля (проекты студии gradle / android):
- Библиотека Android (
com.example.mylib
), который содержит источники и XML, необходимые для определения службы синхронизации, адаптера, средства проверки подлинности и т. д. - Приложение Android: для тестирования / демонстрации функциональности библиотеки (
com.example.mylib.app
).
Это представляется актуальным, поскольку два приложения имеют разные пакеты. По этой причине я настроил sharedUserId
собственность в двух манифестах проекта (и в соответствии с packages.xml
фрагменты ниже, кажется, настроен правильно).
Все необходимые разрешения, кажется, установлены правильно (а именно: READ_SYNC_SETTINGS
, WRITE_SYNC_SETTINGS
, AUTHENTICATE_ACCOUNTS
, USE_CREDENTIALS
, GET_ACCOUNTS
а также MANAGE_ACCOUNTS
).
Я также установил явные значения для свойств манифеста (и не проходя через @string/...
расширения) - см. ниже.
Также пробовал чистые сборки, чистые установки, перезагрузки и т. Д.
Технические детали / свалки следуют.
Окружающая среда / Настройка
- Использование Android Studio (версия 1.3)
targetSdkVersion
22 (для обоих проектов)- Запуск на эмуляторе (genymotion)
Системные дампы logcat
Следуя советам, упомянутым в этом вопросе, я проверил, что Android System Logcat, похоже, тоже в порядке (пока не встретится исключение):
До (чистая установка):
08-10 10:43:39.375 9015-9031/system_process D/PackageManager﹕ New package installed in /data/app/example.mylib.app-1.apk
08-10 10:43:39.387 9015-9027/system_process D/PackageManager﹕ generateServicesMap(android.accounts.AccountAuthenticator): 3 services unchanged
08-10 10:43:39.387 9015-9027/system_process D/PackageManager﹕ generateServicesMap(android.content.SyncAdapter): 6 services:
New service added: ServiceInfo: SyncAdapterType {name=com.example.mylib.provider, type=com.example.mylib.provider.ACCOUNT, userVisible=false, supportsUploading=false, isAlwaysSyncable=true, allowParallelSyncs=false, settingsActivity=null}, ComponentInfo{com.example.mylib.app/com.example.mylib.service.SyncService}, uid 10048
08-10 10:43:39.739 9015-9015/system_process I/ActivityManager﹕ START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.mylib.app/.MyActivity u=0} from pid 19237
08-10 10:43:39.791 9015-9025/system_process I/ActivityManager﹕ Start proc com.example.mylib.app for activity com.example.mylib.app/.MyActivity: pid=19247 uid=10048 gids={3003, 1028}
После прохождения addAccountExplicitly()
:
08-10 10:45:56.479 9015-9270/system_process V/AccountManagerService﹕ addAccount: Account {name=100, type=com.example.mylib.provider.ACCOUNT}, caller's uid 10048, pid 19247
08-10 10:45:56.479 9015-9270/system_process V/AccountManagerService﹕ caller uid 10048 has android.permission.AUTHENTICATE_ACCOUNTS
08-10 10:45:56.479 9015-9270/system_process W/AccountManagerService﹕ caller uid 10048 is different than the authenticator's uid
Пакеты Дамп
Интересные фрагменты из /data/system/packages.xml
вроде бы в порядке
...
<package name="com.example.mylib.app"
codePath="/data/app/com.example.mylib.app-1.apk"
nativeLibraryPath="/data/data/com.example.mylib.app/lib"
flags="0" ft="14f170308d8" it="14f16d8b51b" ut="14f17030a42" version="1"
sharedUserId="10048">
<sigs count="1">
<cert index="4" />
</sigs>
<perms />
</package>
...
<shared-user name="com.example.mylib" userId="10048">
<sigs count="1">
<cert index="4" />
</sigs>
<perms>
<item name="android.permission.READ_SYNC_SETTINGS" />
<item name="android.permission.MANAGE_ACCOUNTS" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="android.permission.WRITE_SYNC_SETTINGS" />
<item name="android.permission.GET_ACCOUNTS" />
<item name="android.permission.INTERNET" />
<item name="android.permission.AUTHENTICATE_ACCOUNTS" />
</perms>
</shared-user>
Манифесты проекта
Библиотека проекта mylib_authenticator.xml
:
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="com.example.mylib"
android:accountType="com.example.mylib.provider.ACCOUNT"
android:exported="true"
android:label="@string/service_name"/>
Библиотека проекта mylib_syncadapter.xml
:
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="com.example.mylib"
android:contentAuthority="com.example.mylib.provider"
android:accountType="com.example.mylib.provider.ACCOUNT"
android:userVisible="false"
android:exported="true"
android:supportsUploading="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"
/>
Интересные фрагменты из библиотечного проекта AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mylib"
android:sharedUserId="com.example.mylib">
<application>
<provider
android:name="com.example.mylib.provider.MyContentProvider"
android:authorities="com.example.mylib.provider"
android:exported="true"
android:syncable="true"/>
<service
android:name="com.example.mylib.service.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/mylib_syncadapter" />
</service>
<service android:name="com.example.mylib.service.AccountService"
android:exported="true">
<intent-filter>
<action android:name="android.content.AccountAuthenticator"/>
</intent-filter>
<meta-data android:name="android.content.AccountAuthenticator"
android:resource="@xml/mylib_authenticator" />
</service>
</application>
Интересные биты из приложений проекта AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mylib.app"
android:sharedUserId="com.example.mylib">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<application ...>
<activity ... />
</application>
</manifest>