Как использовать пользовательские разрешения в Android?
У меня есть два приложения.
Один объявляет разрешение и имеет один Activity
:
Часть AndroidManifest.xml
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:permission="your.namespace.permission.TEST" >
<activity
android:name=".DeclaringPermissionActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp"
android:host="myapp.mycompany.com" />
</intent-filter>
</activity>
</application>
Второй заявляет, что использует разрешение
Часть AndroidManifest.xml
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="your.namespace.permission.TEST" />
<application
Часть Activity
:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("myapp://myapp.mycompany.com/index")));
}
Я устанавливаю приложение с объявлением разрешения, затем запускаю второе приложение.
В результате я получаю исключение безопасности:
01-11 09:46:55.249: E/AndroidRuntime(347): java.lang.RuntimeException: Unable to start activity ComponentInfo{your.namespace2/your.namespace2.UsingPErmissionActivity}: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.VIEW dat=myapp://myapp.mycompany.com/index cmp=your.namespace/.DeclaringPermissionActivity } from ProcessRecord{407842c0 347:your.namespace2/10082} (pid=347, uid=10082) requires your.namespace.permission.TEST
5 ответов
Я создал тестовый код, вы можете использовать его и проверить свои разрешения. Существует два приложения PermissionTestClient, которое объявляет разрешение и защищает свою деятельность этим разрешением. Вот его файл манифеста:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testpackage.permissiontestclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<permission android:name="com.testpackage.mypermission" android:label="my_permission" android:protectionLevel="dangerous"></permission>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:permission="com.testpackage.mypermission"
android:name=".PermissionTestClientActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter >
<action android:name="com.testpackage.permissiontestclient.MyAction" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
В файле Activity нет ничего особенного, поэтому я не буду показывать это здесь.
Приложение PermissionTestServer вызывает активность из PermissionTestClient. Вот его файл манифеста:
<?xml version="1.0" encoding="utf-8"?>
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="com.testpackage.mypermission"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".PermissionTestServerActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
И активность:
package com.testpackage.permissiontestserver;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class PermissionTestServerActivity extends Activity {
private static final String TAG = "PermissionTestServerActivity";
/** Called when the activity is first created. */
Button btnTest;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnTest = (Button) findViewById(R.id.btnTest);
btnTest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Button pressed!");
Intent in = new Intent();
in.setAction("com.testpackage.permissiontestclient.MyAction");
in.addCategory("android.intent.category.DEFAULT");
startActivity(in);
}
});
}
}
Чтобы проверить это, просто удалите использование-разрешения из серверного приложения. Вы получите ошибку нарушения безопасности.
Вам необходимо создать разрешение в манифесте базового приложения, объявив его исключительно. Например:
<permission android:name="your.namespace.permission.TEST"
android:protectionLevel="normal" android:label="This is my custom permission" />
И позже используйте его в желаемом приложении как:
<uses-permission android:name="your.namespace.permission.TEST" />
Примечание. Крайне важно поддерживать порядок, в котором вы устанавливаете приложения с пользовательскими разрешениями. То есть сначала необходимо установить приложение, которое объявляет разрешение, а затем установить приложение, которое его использует. Любое нарушение в этом порядке может нарушить использование обычая. разрешения.
Как указано в ответах, вы также должны учитывать порядок установки приложений.
это важно, потому что:
если приложение, запрашивающее разрешение (приложение B), установлено перед приложением, которое определяет разрешение (приложение A), то такое конкретное разрешение не будет определено для конкретного устройства, поэтому ОС вообще не будет запрашивать разрешение.
позже, когда вы установите приложение A и попытаетесь запустить приложение B, последнее не сможет получить доступ к защищенному компоненту.
Одним из обходных путей может быть определение одного и того же настраиваемого разрешения в обоих приложениях, A и B, чтобы убедиться, что разрешение существует на устройстве независимо от того, какое приложение установлено первым, поэтому, когда приложение A установлено, разрешение уже будет предоставлен приложению Б.
В этом случае, однако, вы должны убедиться, что уровень защиты одинаков в обеих декларациях, поскольку это может привести к угрозе безопасности.
(обратите внимание, что начиная с Android 5.0 и выше вы не можете определять одно и то же разрешение в нескольких приложениях, кроме случаев, когда эти приложения подписаны одним и тем же ключом подписи).
Принятый ответ показывает правильный процесс создания настраиваемых разрешений. У меня есть заметка, чтобы решить, какое разрешение и имя разрешения после моего тестирования
android:protectionLevel="normal" // don't need user confirmation to grant, similar to some low-risk permission like android.permission.INTERNET
android:protectionLevel="dangerous" // need user confirmation to grant // similar to some high-risk permission like android.permission.CAMERA
android:protectionLevel="signature" // both app need to sign with the same signature
На Android < 6 пользователь предоставляет разрешение при установке или обновлении приложения. Android делает это за нас, нам не нужно кодировать
Android >= 6, грант пользователя
dangerous
разрешение при использовании приложения (разрешение во время выполнения). Нам нужно написать код, чтобы запросить разрешение во время выполнения
Имя опасного разрешения Android должно состоять из 2 частей (тест на Android 10, Pixel 4XL),
label
,
description
,
icon
не требуется, чтобы разрешение работало
<permission
android:name="my.MyCustomPermission" // work well
android:name="MyCustomPermission" // not work, the runtime permission dialog won't show
android:label="" // don't required
android:description="" // don't required
android:icon="" // don't required
Определение пользовательских разрешений осуществляется с помощью <Permission>
тег.. Пожалуйста, перейдите по ссылке ниже, чтобы использовать пользовательские разрешения в приложении: