java.lang.SecurityException: uid вызывающего абонента XXXXX не имеет какого-либо из android.permission.GET_ACCOUNTS

Примечание. Это не дубликат, я пробовал много решений в похожих вопросах StackOverflow, и они не сработали в моем случае. Спасибо за любую помощь.

Этот сбой происходит только на устройствах с версией Android старше 6.0. Например, происходит сбой на XT1032 под управлением Android версии 5.1. В этом случае всякий раз, когда я вызываю этот метод, в моем методе onCreate AppCompatActivity,

AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);

Он падает, потому что у него нет необходимого разрешения (и я не знаю почему, потому что оно есть в манифесте). Я считаю, что на самом деле он не входит в метод, но вылетает при входе в метод из-за строки @RequiresPermission:

@RequiresPermission(GET_ACCOUNTS)
    public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
            Handler handler, boolean updateImmediately) { ...

Вот трассировка стека и еще немного кода ведения журнала:

V/AccountManagerService: getAccounts: accountType null, caller's uid 10018, pid 23074
V/AccountManagerService:   caller uid 10018 has android.permission.GET_ACCOUNTS
V/AccountManagerService: getAccounts: accountType null, caller's uid 10018, pid 23074
V/AccountManagerService:   caller uid 10018 has android.permission.GET_ACCOUNTS
V/AccountManagerService:   caller uid 10009 has android.permission.INTERACT_ACROSS_USERS
V/AccountManagerService: getAccounts: accountType com.google, caller's uid 10009, pid 1738
V/AccountManagerService:   caller uid 10009 has android.permission.GET_ACCOUNTS
V/AccountManagerService: getAccounts: accountType null, caller's uid 10018, pid 23074
V/AccountManagerService:   caller uid 10018 has android.permission.GET_ACCOUNTS
V/AccountManagerService: getAccounts: accountType null, caller's uid 10156, pid 13722
W/AccountManagerService:   caller uid 10156 lacks any of android.permission.GET_ACCOUNTS

java.lang.RuntimeException: Unable to start activity ComponentInfo{MainActivity}: java.lang.SecurityException: caller uid 10156 lacks any of android.permission.GET_ACCOUNTS
                                                                                             at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
                                                                                             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
                                                                                             at android.app.ActivityThread.access$800(ActivityThread.java:151)
                                                                                             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
                                                                                             at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                             at android.os.Looper.loop(Looper.java:135)
                                                                                             at android.app.ActivityThread.main(ActivityThread.java:5254)
                                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                                             at java.lang.reflect.Method.invoke(Method.java:372)
                                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                                                                                          Caused by: java.lang.SecurityException: caller uid 10156 lacks any of android.permission.GET_ACCOUNTS
                                                                                             at android.os.Parcel.readException(Parcel.java:1546)
                                                                                             at android.os.Parcel.readException(Parcel.java:1499)
                                                                                             at android.accounts.IAccountManager$Stub$Proxy.getAccounts(IAccountManager.java:728)
                                                                                             at android.accounts.AccountManager.getAccounts(AccountManager.java:407)
                                                                                             at android.accounts.AccountManager.addOnAccountsUpdatedListener(AccountManager.java:2372)

Что такое uid вызывающего абонента и почему он использует uid 10156 вместо 10018 или 10009, у которых есть разрешение?

Я убедился, что строка типа моей учетной записи в AuthenticationService совпадает с типом учетной записи в файле authentication.xml, и они оба используют жестко запрограммированные строки (а не ресурсы String).

public class AuthenticationService extends Service {

    public static final String ACCOUNT_TYPE = "com.mywebsite";
    ...
    public static boolean createAccount(String username,...) {

        AccountManager am = AccountManager.get(Application.getInstance());
        Account account = new Account(username, ACCOUNT_TYPE);

И мой аутентификатор:

<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
                       android:accountType="com.mywebsite"
                       android:icon="@mipmap/ic_launcher"
                       android:smallIcon="@mipmap/ic_launcher"
                       android:label="@string/app_name"
    />

У меня тоже так: <uses-permission android:name="android.permission.GET_ACCOUNTS" /> в теге <manifest>, а не в теге <application>. Манифест:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mywebsite.android.department.departmentname” >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
    <uses-permission android:name="android.permission.READ_LOGS"/>

    <application
        android:name=".Application"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name”>
        <service android:name=".auth.AuthenticationService" >
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator" />
            </intent-filter>

            <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator" />
        </service>

    </application>

</manifest>

Кажется, это подсказка в документации Android, но, похоже, она не коррелирует с моей ошибкой, потому что у меня есть разрешение в манифесте (http://developer.android.com/reference/android/Manifest.permission.html#GET_ACCOUNTS):

Примечание. Начиная с Android 6.0 (уровень API 23), если приложение использует подпись аутентификатора, управляющего учетной записью, ему не требуется разрешение «GET_ACCOUNTS» для чтения информации об этой учетной записи. В Android 5.1 и более ранних версиях всем приложениям требуется разрешение «GET_ACCOUNTS» для чтения информации о любой учетной записи.


person Rock Lee    schedule 25.04.2016    source источник
comment
Что такое uid вызывающего абонента — это идентификаторы пользователей Linux (uid) приложений, вызывающих какой-либо метод, который перенаправляется к AccountManagerService. и почему он использует uid 10156 вместо 10018 или 10009, у которых есть разрешение? -- предположительно, ваше приложение имеет uid 10156. Вероятно, другие uid предназначены для других приложений на устройстве.   -  person CommonsWare    schedule 26.04.2016
comment
Хорошо, я разместил весь манифест. Спасибо @CommonsWare   -  person Rock Lee    schedule 26.04.2016
comment
Попробуйте это, он будет работать на уровне API 23 stackoverflow.com/a/41221852/5488468   -  person Bipin Bharti    schedule 19.12.2016


Ответы (1)


Оказывается, был конфликт с библиотекой, которую я использовал. В частности, служба поддержки библиотеки сказала мне:

Слой SDK запрашивает разрешение GET_ACCOUNTS, используя maxSdkVersion, равное 18. Может показаться, что когда манифесты объединяются, это перезаписывает запрос на разрешение в вашем манифесте, поэтому это разрешение не запрашивается для 19+.

Решение состояло в том, чтобы изменить мой манифест следующим образом:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />

к этому:

<uses-permission android:name="android.permission.GET_ACCOUNTS" tools:node="replace" />

В частности, добавление tools:node="replace".

Для получения дополнительной информации см. этот ответ на мой другой вопрос: https://stackoverflow.com/a/37013603/2423194

person Rock Lee    schedule 03.05.2016