Android(安卓)动态权限最全解析
本文目录
- 动态权限概述
- 动态权限分类
- 动态权限申请方法
- 方法1:官方API提供的方法
- 步骤1:检查是否有权限
- 步骤2:申请权限
- 步骤3:回调函数的处理
- 完整代码
- 方法2:RxPermission
- 引入依赖
- 声明权限
- 申请单个权限
- 申请多个权限
- 方法3:AndPermission
- 引入依赖
- 申请单个或多个权限
动态权限概述
从Android6.0
开始,Google调整了应用的权限申请方案。调整之后将权限分级,分成了普通权限
和危险权限
,普通权限的授权方式跟之前一样,只需要在Manifest
文件中申明即可,危险权限不仅需要在Manifest
文件中声明,还需要在程序中调用官方提供的Api主动申请。
动态权限分类
Android6.0
以后,一共将动态权限分成了9组,每组只要有一个权限申请成功了,就默认整组权限都可以使用了。这九组权限分别如下:
权限组名称 | 权限组 | 权限组权限成员 |
---|---|---|
读写联系人 | group:android.permission-group.CONTACTS | permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS |
电话 | group:android.permission-group.PHONE | permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAIL |
日历信息 | group:android.permission-group.CALENDAR | permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR |
相机 | group:android.permission-group.CAMERA | permission:android.permission.CAMERA |
传感器 | group:android.permission-group.SENSORS | permission:android.permission.BODY_SENSORS |
地理位置 | group:android.permission-group.LOCATION | permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION |
存储卡 | group:android.permission-group.STORAGE | permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE |
多媒体 | group:android.permission-group.MICROPHONE | permission:android.permission.RECORD_AUDIO |
SMS | group:android.permission-group.SMS | permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS |
动态权限申请方法
方法1:官方API提供的方法
步骤1:检查是否有权限
由于低于API 23
是不需要使用动态权限申请的,我们需要先判断一下系统版本,代码如下是Android 6.0以上
的系统还是Android 6.0以下
的系统。用ContextCompat
类中的checkSelfPermission
方法进行是否有权限判断。
public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());}
具体使用方法如下:
if (Build.VERSION.SDK_INT >= 23) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //无该权限,需要申请 }} else { //低于23 不需要处理}
步骤2:申请权限
在步骤的的checkSelfPermission
方法中如果判断没有权限,就需要用到ActivityCompat
类中的requestPermissions
方法进行动态权限申请,该方法需要传一个需要申请权限名称的权限permissions
数组。
public static void requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {}
申请方法如下:先定一个需要申请权限的权限数组PERMISSIONS_STORAGE
private static final int REQUEST_EXTERNAL_STORAGE = 1;private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"};ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
步骤3:回调函数的处理
由于权限申请是异步的,用户完成了以后,需要回调函数处理,
Activity
中提供了一个回调处理方法onRequestPermissionsResult
,只需要重写该方法即可
case 中的参数REQUEST_EXTERNAL_STORAGE
即步骤2申请权限中定一个的参数
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_EXTERNAL_STORAGE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show(); } } } }
完整代码
我们以申请SD卡读写权限为例,完整代码如下:
public class MainActivity extends AppCompatActivity { private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = {"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= 23) { checkPermission(); } } private void checkPermission() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission .WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, "请开通相关权限,否则无法正常使用本应用!", Toast.LENGTH_SHORT).show(); } //申请权限 ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } else { Toast.makeText(this, "已授权成功!", Toast.LENGTH_SHORT).show(); dothings(); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_EXTERNAL_STORAGE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { dothings(); Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show(); } } } } public void dothings() { }}
AndroidManifest.xml声明权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
方法2:RxPermission
RxPermission
可以帮助开发者简化获取权限的相关处理操作,而且内部也自动帮我们判断了版本是否需要申请权限。同时结合RxJava
可以方便的回调各种结果。
官网:https://github.com/tbruyelle/RxPermissions
引入依赖
allprojects { repositories { ... maven { url 'https://jitpack.io' } }} dependencies { implementation 'com.github.tbruyelle:rxpermissions:0.10.2' implementation 'io.reactivex.rxjava2:rxjava:2.0.1' implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'}
由于rxpermissions
需要用到rxjava,所有rxjava
的包也一起引入。
声明权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA"/>
申请单个权限
RxPermissions permissions = new RxPermissions(this);permissions.request(Manifest.permission.CAMERA) .subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) { if (aBoolean ) { Toast.makeText(MainActivity.this, "授权成功!", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "授权失败!", Toast.LENGTH_SHORT).show(); } } });
申请多个权限
RxPermissions permissions = new RxPermissions(this); permissions.request(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE) .subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) { if (aBoolean ) { Toast.makeText(MainActivity.this, "授权成功!", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this, "授权失败!", Toast.LENGTH_SHORT).show(); } } });
方法3:AndPermission
AndPermission
跟前面的RxPermission
使用方法类似
官网:https://github.com/yanzhenjie/AndPermission
引入依赖
implementation 'com.yanzhenjie:permission:2.0.3'
申请单个或多个权限
AndPermission.with(this) .runtime() .permission(Permission.WRITE_EXTERNAL_STORAGE,Permission.CAMERA) .onGranted(permissions -> { Toast.makeText(MainActivity.this, "授权成功!", Toast.LENGTH_SHORT).show(); }) .onDenied(permissions -> { Toast.makeText(MainActivity.this, "授权失败!", Toast.LENGTH_SHORT).show(); }) .start();
效果如下:
更多相关文章
- 事件处理机制之Gestures(手势)
- Android(安卓)—— 注解(Annotation)也被称为元数据(Metadata)
- Android权限申请的学习实践
- Android获取WIFI的BSSID遇到的坑(已解决)
- Android基础笔记(十一)- Service基础和注意事项以及Activity与Serv
- Android异步处理机制AsyncTask的理解
- Android(安卓)View源码解读:浅谈DecorView与ViewRootImpl
- Android(安卓)如何获取当前Activity实例对象?
- Android(安卓)AsyncTask 异步任务之源码解析