2016-07-06 3 views
30

фонAndroid пользовательских разрешений - Зефир

Исторически Android Персонализированные разрешения have been a mess и were install order dependent, который был известен expose vulnerabilities.

До появления API 21 было нерешенное временное решение, в котором объявлялось пользовательское разрешение другого приложения в вашем манифесте, предоставлялось разрешение ... Однако, поскольку API 21, только одно приложение может объявлять пользовательские разрешения и устанавливать другое приложение, объявляющее это же разрешение, будет предотвращено.

Альтернативами являются переустановка приложения, требующего разрешения, поэтому они обнаруживаются системой, но это is not a good user experience. Или проверьте во время выполнения для разрешений вызывающего приложения, но that is not without its theoretical flaws.

Проблема

На Android Зефира (6.0 - API 23) приложение должно запросить разрешение от пользователя, использовать свое собственное разрешение. Объявленное пользовательское разрешение не предоставляется автоматически.

Это кажется странным, учитывая, что только одно приложение может его объявить.

Для репликации

Объявите пользовательского разрешения и BroadcastReceiver в манифесте.

<permission 
    android:name="com.example.app.permission.CONTROL_EXAMPLE_APP" 
    android:description="@string/control_description" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/control_label" 
    android:protectionLevel="normal or dangerous"/> 

<uses-permission 
    android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/> 

// etc 

<receiver 
    android:name="com.example.app.MyBroadcastReceiver" 
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 
    <intent-filter android:priority="999"> 
     <action android:name="com.example.app.REQUEST_RECEIVER"/> 
    </intent-filter> 
</receiver> 

С приложением третьей стороной, заявить, что она использует пользовательское разрешение в манифесте (и принять его с помощью диалога или настройки) и вызовите:

final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER"); 

    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() { 
     @Override 
     public void onReceive(final Context context, final Intent intent) { 

     // getResultCode(); 

     } 
    }, null, Activity.RESULT_CANCELED, null, null); 

Результат будет возвращать ОТМЕНЕН и журнал будет показывать:

system_process Вт/BroadcastQueue: Разрешение отказа: прием Intent { акт = com.example.app.REQUEST_RECEIVER FLG = 0x10 (имеет дополнительные услуги)} до com.example.app/.MyBroadcastReceiver требует com.example.app.permission.CONTROL_EXAMPLE_APP из-отправителя com.example.thirdparty

Если я использую стандартный диалог ActivityCompat.requestPermissions(), чтобы позволить пользователю принять разрешение , приемник, как и следовало ожидать, работает правильно.

Вопрос

Это ожидаемое поведение? Или я почему-то что-то упустил?

Казалось бы смешно, чтобы поднять диалог, сообщающий

Приложение Пример App хочет разрешение использовать пример приложения

И это может действительно относятся к пользователю, предоставляя им такой бессмысленный запрос.

Я могу, конечно, изменить описание и имя разрешений на то, что они будут принимать, например «общаться с другими установленными приложениями», но прежде чем вздохнуть и принять этот подход, я подумал, что попрошу об этом вопрос.

Примечание

Пример упорядоченной трансляции, чтобы повторить эту проблему. Мое приложение использует другие реализации поставщиков контента и связанную службу. Это не альтернативная реализация, которую я требую, это подтверждение проблемы.

Благодарим за внимание.

Редактировать: Чтобы уточнить, для других реализаций, таких как объявление разрешения на службу (которое было бы наиболее просто реплицироваться), автоматически выдано объявленное пользовательское разрешение.

+1

FWIW, я не могу воспроизвести вашу проблему, по крайней мере, на Android 7.1 (Google Pixel). Я скопировал ваш код в новый проект Android Studio и не испытываю проблем с отправкой трансляции с клиента на приемник и получением ответа. Теперь мой образец может быть проще вашего (например, оба приложения подписаны одним и тем же ключом для подписания). Если вы можете создать пример приложения, которое последовательно воспроизводит эту проблему, и вы можете воспроизвести его на 7.1, [file the issue] (http://b.android.com) против предварительного просмотра разработчика, включая пример приложения и полные инструкции. – CommonsWare

+0

Чтобы быть понятным, вы просите руководство, как запросить разрешение у пользователя разумным образом, что он не будет отрицать? или вы просите предложить решение, когда он отклонит ваше разрешение, какими могут быть возможности? я запутался –

+0

Я думаю, что тот факт, что приложение запрашивает собственное разрешение, можно интерпретировать как «главный переключатель», что-то вроде: «позволить другим приложениям управлять этим приложением». И хотя разрешение должно быть предоставлено в сторонних приложениях (тоже), чтобы иметь возможность контролировать пример приложения, некоторые пользователи могут фактически использовать его, чтобы полностью исключить функцию «управляемости». (Но все же нечетно, что сервис, например, автоматически получает пользовательское разрешение ...) – Gyebro

ответ

-1

Хотя для пользователя может быть неоднозначным видеть запрос на разрешение для приложения, которое объявлено в том же приложении, это то, как андроид предназначен для запуска с зефира. Я думаю, что в перспективе андроида поведение такое, как предполагалось и правильно.

+0

Это утверждение не может быть правильным, так как пользовательское разрешение автоматически предоставляется при других обстоятельствах - поэтому оно не является универсальным «по дизайну», – brandall

0

Я думаю, что проблема в вашем примере заключается в том, что вы явно требуете, чтобы и вашим приложениям было предоставлено специальное разрешение.

Эта часть требует, что com.example.thirdparty приложение имеет разрешение:

<receiver 
    android:name="com.example.app.MyBroadcastReceiver" 
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 

И эта часть требует, что com.example.app приложение имеет разрешение, а также:

context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", ... 

Вы упомянули, что у вас нет этой проблемы при использовании услуги. Я не знаю, как именно вы используете сервис, но если вы просто объявить его как это:

<service 
    android:name="com.example.app.MyService" 
    android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 

, а затем привязать его следующим образом:

context.bindService(serviceIntent, mServiceConnection, ... 

, то это достаточно, если com.example .thirdparty имеет разрешение, а com.example.app не нужно иметь его.

Другими словами, я думаю, что это поведение является, и разница, которую вы видите между Broadcast и поведением службы, потому что в случае широковещательного вы специально просить com.example.app имеет настраиваемое разрешение, тогда как в Служебном случае вы этого не делаете.

Надеюсь, я не понял вашу проблему неправильно. Если бы я это сделал, сообщите мне, и я удалю этот ответ.

-2

Сначала нужно добавить разрешения в файле манифеста после

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
1

Как я понял, вы пытались сделать следующую вещь (по крайней мере, то, как я был в состоянии воспроизвести проблему):

  1. Вы сначала объявите свое новое пользовательское разрешение (позвоните по этому адресу F) приложение

    <permission 
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP" 
        android:description="@string/control_description" 
        android:icon="@mipmap/ic_launcher" 
        android:label="@string/control_label" 
        android:protectionLevel="normal or dangerous"/> 
    
  2. Вы определяете, что ваше приложение F использует разрешение com.example.app.permission.CONTROL_EXAMPLE_APP. Это правильно, как говорится в руководстве.

    <uses-permission 
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/> 
    
  3. Вы объявляете свой собственный вещательный приемник в своем приложении F. Для связи с этим транслировать ваше приложение (это независимо от того, какой из них, F или другое приложение), должен получить пользовательского разрешения

    <receiver 
        android:name="com.example.app.MyBroadcastReceiver" 
        android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP"> 
        <intent-filter android:priority="999"> 
         <action android:name="com.example.app.REQUEST_RECEIVER"/> 
        </intent-filter> 
    </receiver> 
    
  4. Вы определяете, что вы второй (назовете его S) приложение использует com.example.app.permission.CONTROL_EXAMPLE_APP разрешения. Поскольку вы хотите разрешить S-приложению отправлять широковещательные сообщения в приемник F-приложений.

    <uses-permission 
        android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/> 
    
  5. Наконец, вы пытаетесь отправить широковещательное сообщение из своего S-приложения, используя этот код.

    final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER"); 
    context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() { 
         @Override 
         public void onReceive(final Context context, final Intent intent) { 
          // getResultCode(); 
         } 
        }, null, Activity.RESULT_CANCELED, null, null); 
    

    И это важно, вы получили разрешение на ваш S приложение, но не дать разрешение на ваш F приложения.

    В результате ваш вещательный приемник, заявленный в приложении F, ничего не получил.

  6. После того, как вы предоставили разрешение на свое приложение F (обратите внимание, что теперь S и F предоставили вам специальное разрешение) все работает нормально. Приемник широковещательной передачи, объявленный в сообщении приложения F из приложения S.

Я думаю, что это правильное поведение, потому что это doc говорит нам:

Обратите внимание, что в этом примере, разрешение DEBIT_ACCT не только объявлен с элементом, его использование также просил с элементом . Вы должны запросить его использование для того, чтобы других компонентов приложения запустили защищенную активность, , даже если защита наложена самим приложением.

И приложение, которое объявляет разрешение, также должно запрашивать такое же разрешение для связи с самим собой.

В результате, API Android 23 должен получить доступ, прежде всего, для использования вашей формы разрешения. И мы должны получить 2 предоставленных разрешения, сначала из F-приложения (потому что guidline говорит, что это), и второе из S-приложения (потому что нам просто нужно получить доступ).

Но я не расслышал ваш следующий пункт:

Казалось бы смешно, чтобы поднять диалог, сообщающий

Приложение Пример App хочет разрешение использовать пример приложения

Мой родной Android API 23 показывает мне что-то вроде этого:

Приложение Пример App хочет

0

Я не думаю, что это совершенно верно, что заявленная на заказ разрешение не будет автоматически предоставляться приложению. Ибо, когда пользовательское разрешение имеет уровень защиты «обычный» или «подпись», тогда разрешение предоставляется во время установки. В противном случае, если уровень защиты «опасен», то это разрешение времени выполнения, и оно работает так же, как и другие опасные разрешения: вам нужно будет предложить пользователю предоставить разрешение на приложение.

Смежные вопросы