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 Studio):

  • Библиотека 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

Следуя совету, упомянутому в этом вопросе, Я проверил, что Logcat системы Android тоже в порядке (пока не возникнет исключение):

До (чистая установка):

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>

Interesting bits from app project's 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>

person scooz    schedule 10.08.2015    source источник
comment
У вас есть решение для этого ??   -  person bGorle    schedule 13.02.2018