关于动态权限

首发于个人公众号html

关于动态权限java

一、在给app升级动态权限以前须要注意搞清楚一下几个概念

1.一、版本号对应的api等级

查阅官网能够看出android

1.二、minSdkVersion、targetSdkVersion和 compileSdkVersion

这几个属性一般在gradle defaultConfig中去配置,做用以下shell

(1)minSdkVersion 指明应用程序运行所需的最小API level,若是系统的API level低于minSdkVersion设定的值,那么android系统会阻止用户安装这个应用,若是不指明的话,默认是1,若是指明这个属性,并在项目中使用了改与这个API level的API的话,那么将会在编译时报错。 可见该属性不只在程序安装时起做用,并且会在项目构建时起做用apache

(2)targetSdkVersionapi

指明应用程序目标API level的一个整数,若是不设置就默认和minSdkVersion相同。这个属性通知系统,已经针对这个目标版本测试过程序,系统没必要使用兼容模式来让你的应用程序向前兼容这个目标版本。 若是targetSdkVersion为19(对应为Android4.4),应用运行时,最高只能使用API 19的新特性。即便代码中使用了API 23的新特性,实际运行时,也不会使用该新特性; 可见targetSdkVersion这个属性是在程序运行时期起做用的,系统根据这个属性决定要不要以兼容模式运行这个程序 例如,Android6.0系统增长了动态权限机制,若是为了追时髦,盲目把你的targetSDKVersion设置为23(6.0),那么在须要使用权限的地方将会出现异常。为此,在你作好动态权限申请以前,为保障APP正常运行,你须要将目标版本设置低于23。缓存

(3)complieSdkVersionbash

compileSdkVersion仅仅是告诉Gradle使用哪一个版本的SDK编译应用,不会被包含到apk中,彻底不影响应用的运行结果;虽然没有影响可是网络

即 :compileSDKVersion是和编译器打交道的,而minSDKVersion和targetSDKVersion是和系统打交道的。app

二、如何升级app的动态权限

首先须要了解动态权限这个概念

2.1 动态权限

这个是在android 6.0提出的,从该版本开始,用户实在运行时而不是应用安装时授予或者撤销应用权限,对应API23,这个版本最重要的变化就是权限动态管理,任何未被授予权限的逻辑均可能引发后续运行的崩溃,能够经过adb 工具从命令行获取权限

按组列出权限和状态:

$ adb shell pm list permissions -d -g

授予或撤销一项或多项权限:

$ adb shell pm [grant|revoke] ...

6.0以前的权限在AndroidMenifest声明以后便可获取全部权限,这样会形成用户会默默忍受一些没必要要的权限,特别是通信录,位置短信之类的比较敏感的权限,在6.0以后咱们只有在须要权限的时候才会向用户请求,用户能够选择拒绝,新的机制较好的保护的用户的隐私。 谷歌将权限分为两大类 Normal Permissions 这类权限通常不涉及用户隐私是不须要用户进行受权的,好比网络访问、蓝牙(详细权限见附录) Dangenerous Permission 这类涉及到用户隐私,须要用户进行受权,好比读取sdcard、开启照相机、访问通信录等,其中危险权限是分组的,用户以前若是已经选择经过该组某个危险权限,主要有如下几组(详细权限见附录)

  1. 身体传感器
  2. 日历 摄像头
  3. 通信录
  4. 地理位置
  5. 麦克风
  6. 电话
  7. 短信
  8. 存储空间

2.2 权限相关API

为了方便开发者实现权限管理,谷歌给出下面4个API

通常权限检查须要如下三个步骤配合

一、检查权限是否授予

//Activity.java
> public int checkSelfPermission(permission) 
复制代码

这个是在ContextCompat类中用来判断是否app已经获取到某一个权限的使用权。若是返回android.content.pm.PackageManager#PERMISSION_GRANTED,则说明app被授予权限,若是返回android.content.pm.PackageManager#PERMISSION_DENIED 则说明权限被禁止授予

二、申请权限

//Activity.java
public final void requestPermissions( new String[permission1,permission2,...], requestCode)
复制代码

这个是在ActivityCompat类以及FragmentCompat类中用来申请权限的方法

三、权限回调 用户在系统弹窗里面选择之后结果会经过Activity的onRequestPermissionsResult 方法回调

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
    //继续执行逻辑或者提示权限获取失败
}
复制代码

这些方法能够封装在BaseActvity中

四、是否显示权限对话框 这个是做为辅助类

public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission) 这个是在ActivityCompat类以及FragmentCompat类中用来判断是否显示权限询问对话框。在权限申请的过程当中,若是用户选择容许权限使用或者在拒绝的同时又勾选了再也不询问对话框,这2种状况下该api就会返回false,表示再也不弹出权限询问对话框,其中受权弹窗是不支持自定义的

这个辅助函数十分重要,当动态权限申请时候若是用户若是用户勾选了“再也不询问”,那么在执行requestPermissions( )后,onRequestPermissionsResult( )会永远返回PERMISSION_DENIED,这样应用本来的操做将永远没法执行,这是咱们不但愿看到的

谷歌仍是给咱们留了一手,就是 shouldShowRequestPermissionRationale,若是返回true,应用应该弹出dialog说明申请权限的原因好比下面这种

其中第一次申请权限时候该函数默认返回false,无需告知用户申请该权限的理由;当第一次申请被拒绝,再次申请时该函数会返回true,而且弹出的系统dialog上会有一个选择“再也不询问”,要是用户勾选了该选项,则之后该函数一直会返回false。

2.3 如何适配

若是项目的targetSdkVersion < 23 运行在android 6.0及以上的系统上,会默认给与AndroidManifest.xml中申请的权限,是否是这样就万事大吉了呢?显然是想多了,若是用户在应用的权限页面手动回收权限,将会致使应用crash

虽然系统提醒了用户,可是仍是要取决用户心情,所以稳妥的适配动态仍是有必要的事情。

首先targetSdkVersion小于23的应用默认授予了所申请的全部权限,因此若是你之前的APP设置的targetSdkVersion低于23,也能正常使用。等于或者大于23,则必须 request permission,不然会崩溃闪退。 下面将大体阐述一下升级动态权限步骤

(1)声明目标版本sdk 修改build.gradle中targetSdkVersion为23以上

(2)检查权限申请地方并request权限 在咱们须要使用到权限的地方,检查是否已经拥有权限,好比读写外置SD卡权限,咱们在写入以前检车是否有权限,没有权限则申请权限

private void requestContactPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {
            //申请 WRITE_CONTACTS 权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS},
                    REQUEST_CODE_WRITE_CONTACTS);
        }
    } 
复制代码

(3)响应用户权限回调

用户能够选择allow或者deny,可能deny。回调onRequestPermissionsResult方法, 该方法相似于onActivityResult。若是是fragment,最好是使用父fragment,但不是使用ActivityCompat。建议使用getParentFragment().requestPermissions方法。

(4)根据requestCode和grandResult(受权结果)作相应处理

private void handleGrantResults(int requestCode, int[] grantResults) {
      if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
          if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
              // Permission Granted 得到权限后执行xxx
          } else {
              // Permission Denied 拒绝后xx的操做。
          }
      }
  }
复制代码

三、后话

3.一、权限申请若是用户拒绝怎么处理

若是用户拒绝了核心权限一次,下次再次申请会出现再也不提醒的选项,要是选择再也不提醒,核心权限不给获取一些功能就没法使用,你能够选择直接退出应用,或者能够优雅点,咱们本身检测一下是否拒绝了两次或者以上,本身给个提示向用户作一个交互

private void handleContactPermission() {
        if (Integer.parseInt(Build.VERSION.SDK)>=23) {
            int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS);
            if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
                if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {
                    showMessageOKCancel("You need to allow access to Contacts",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    requestContactPermission();//肯定后申请权限。
                                }
                            });
                    return;
                }
                requestContactPermission();//没有权限的话,申请。
            }
        }
复制代码

或者记录用户勾选了再也不询问 Google提供了一个很是好的思路,详见EasyPermissions . EasyPermissions并无存储上一次shouldShowRequestPermissionRationale( )的返回值,而是在申请权限被拒后调用shouldShowRequestPermissionRationale( )方法,若是此时返回false则说明用户勾选了“再也不询问”。

两种方式均可以做为参考方式。

3.2 取消支持Apache http 客户端

Android 6.0 版移除了对 Apache HTTP 客户端的支持。若是您的应用使用该客户端,并以 Android 2.3(API 级别 9)或更高版本为目标平台,请改用HttpURLConnection 类。此 API 效率更高,由于它能够经过透明压缩和响应缓存减小网络使用,并可最大限度下降耗电量。要继续使用 Apache HTTP API,您必须先在 build.gradle 文件中声明如下编译时依赖项: android { useLibrary 'org.apache.http.legacy' }

3.3 升级到7.0 api 24及以上

对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。若是一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常,常见的是访问升级下载到内部sd卡,访问手机相册等。 网上有不少解决方案

附录

Normal Permissions

ACCESS_LOCATION_EXTRA_COMMANDS

ACCESS_NETWORK_STATE

ACCESS_NOTIFICATION_POLICY

ACCESS_WIFI_STATE

BLUETOOTH

BLUETOOTH_ADMIN

BROADCAST_STICKY

CHANGE_NETWORK_STATE

CHANGE_WIFI_MULTICAST_STATE

CHANGE_WIFI_STATE

DISABLE_KEYGUARD

EXPAND_STATUS_BAR

GET_PACKAGE_SIZE

INSTALL_SHORTCUT

INTERNET

KILL_BACKGROUND_PROCESSES

MODIFY_AUDIO_SETTINGS

NFC

READ_SYNC_SETTINGS

READ_SYNC_STATS

RECEIVE_BOOT_COMPLETED

REORDER_TASKS

REQUEST_INSTALL_PACKAGES

SET_ALARM

SET_TIME_ZONE

SET_WALLPAPER

SET_WALLPAPER_HINTS

TRANSMIT_IR

UNINSTALL_SHORTCUT

USE_FINGERPRINT

VIBRATE

WAKE_LOCK

WRITE_SYNC_SETTINGS

Dangenerous Permission

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

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

###参考连接

公众号小.jpg
相关文章
相关标签/搜索