转载

浅谈Android 6.0之Runtime Permissions

前言

Android6.0发布后,其一系列新特新足够让我们这些Android程序员兴奋一段时间了。首先我们先看看具体有哪些新特性:

-锁频下语音搜索

-指纹识别

-更完整的应用权限管理

-Doze电量管理

-Now on Tap

-App link

具体可以参考 Android 6.0有哪些新特性 。

上面六个新特性中 更完整的应用权限管理 应该是和我们开发者关系最密切的了,接下来我们就来具体了解一下如何在Android 6.0上更好的使用Android系统权限。

Runtime Permissions

在Android 6.0中谷歌摒弃了之前的 install time permissions model 取而代之的是 runtime permissions model 。先来说说 install time permissions model ,这个大家不陌生,就是当Android App安装的时候会向用户展示一坨权限,如果此时用户选择安装,则表示用户同意将这些权限赋予App,如果用户不同意那么这个App就会取消安装。 runtime permissions model 就牛逼了,在App安装的时候同样会向用户展示所需要的权限,并且在用户选择安装App的时候并不表示用户将这些权限赋予了App,而是需要App在运行阶段主动去申请这些权限。这样做的好处显而易见,App对权限的申请对于用户来说变得更加透明,而且用户对App权限的控制也更加灵活。

权限的分类

Android将系统权限分成了四个保护等级 normal , dangerous , signature , signatureOrSystem ,其中最常见的是 normal permissiondangerous permission 两类。

normal permission涵盖的一系列权限的共同点是:App需要访问App运行沙盒以外的数据或资源,但是这些资源对用户的隐私或其他App的危险性较小,下面列举一下这些权限:

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

FLASHLIGHT

GET_PACKAGE_SIZE

INTERNET

KILL_BACKGROUND_PROCESSES

MODIFY_AUDIO_SETTINGS

NFC

READ_SYNC_SETTINGS

READ_SYNC_STATS

RECEIVE_BOOT_COMPLETED

REORDER_TASKS

REQUEST_INSTALL_PACKAGES

SET_TIME_ZONE

SET_WALLPAPER

SET_WALLPAPER_HINTS

TRANSMIT_IR

USE_FINGERPRINT

VIBRATE

WAKE_LOCK

WRITE_SYNC_SETTINGS

SET_ALARM

INSTALL_SHORTCUT

以上这些就是Android 6.0中所有的 normal permissions 了。

dangerous permissions 涵盖的一系列权限的共同点是:这些权限会读写用户的隐私信息,也可能会读写用户存储的数据或影响其他App的正常运行。下面例举出这些权限:

| 权限组| 权限|

|------------------|--------------------------------------------------------------------------------------------------------------|

|CALENDAR | READ_CALENDAR,WRITE_CALENDAR |

|CAMERA | CAMERA |

|CONTACTS | READ_CONTACTS,WRITE_CONTACTS,GET_ACCOUNTS |

|LOCATION | ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION |

|MICROPHONE | RECORD_AUDIO |

|PHONE | READ_PHONE_STATE,CALL_PHONE,READ_CALL_LOG,WRITE_CALL_LOG,ADD_VOICEMAIL,USE_SIP,PROCESS_OUTGOING_CALLS |

|SENSORS | BODY_SENSORS |

|SMS | SEND_SMS,RECEIVE_SMS,READ_SMS,RECEIVE_WAP_PUSH,RECEIVE_MMS |

|STORAGE | READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE |

以上这些权限就是Android6.0中所有的 dangerous permissions

Runtime Permissions针对的是 dangerous permissionsnormal permissions 还是会在App安装期间被默认赋予。

实战

下面我们就以 STORAGE 组中的 WRITE_EXTERNAL_STORAGE 为例子,尝试在Android 6.0中使用 runtime permission 相关api。

我们要做的事情非常简单,在手机的存储设备上新建一个hello.txt。

1.在AndroidManifest文件中添加如下权限生命

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

2.在MainActivity中添加如下方法:

 //在sdcard上新建一个名为fileName的文件 private void createFile(String fileName){  File sdcard = Environment.getExternalStorageDirectory();  File newFile = new File(sdcard,"/" + fileName) ;  if(!newFile.exists()){   try {    newFile.createNewFile();   } catch (IOException e) {    e.printStackTrace();   }  } } 

好的,如果没有 runtime permissions 这个概念的话,那其实这个功能已经完成了,我们来看看它在Android 6.0之前的版本上的运行情况,

首先是安装时的界面:

浅谈Android 6.0之Runtime Permissions

它提示用户该应用会修改会删除SD卡的内容,如果此时用户选择安装,那么也就是默认将 WRITE_EXTERNAL_STORAGE 这个权限赋予了该应用。

再来看运行结果:

浅谈Android 6.0之Runtime Permissions

看吧,文件直接就创建成功了,这样真的是很危险的。

接下来再在Android6.0的机子上安装这个应用,安装截图如下:

浅谈Android 6.0之Runtime Permissions

这个安装界面和之前的一样,也是向用户展示了App所涉及的权限。

下面看运行结果:

浅谈Android 6.0之Runtime Permissions

这里就出问题了,log显示App没有权限在SD卡上创建文件。这里要再讲一下 runtime permissions 原理

对于权限分类中的 dangerous permissions ,runtime permissions要求App在运行的时候做权限请求,某则App则无法获得相应请求。

接下来看一下怎么在代码中进行权限的申请:

 public static final int EXTERNAL_STORAGE_REQ_CODE = 10 ; public void requestPermission(){     //判断当前Activity是否已经获得了该权限     if (ContextCompat.checkSelfPermission(this,      Manifest.permission.WRITE_EXTERNAL_STORAGE)      != PackageManager.PERMISSION_GRANTED) {  //如果App的权限申请曾经被用户拒绝过,就需要在这里跟用户做出解释  if (ActivityCompat.shouldShowRequestPermissionRationale(this,   Manifest.permission.WRITE_EXTERNAL_STORAGE)) {      Toast.makeText(this,"please give me the permission",Toast.LENGTH_SHORT).show();  } else {      //进行权限请求      ActivityCompat.requestPermissions(this,       new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},       EXTERNAL_STORAGE_REQ_CODE);  }     } } 

当进行权限申请,并且用户做出选择后会回调onRequestPermissionsResult这个方法,在这个方法中做相关处理

 @Override public void onRequestPermissionsResult(int requestCode,             String permissions[], int[] grantResults) {  switch (requestCode) {   case EXTERNAL_STORAGE_REQ_CODE: {    // 如果请求被拒绝,那么通常grantResults数组为空    if (grantResults.length > 0      && grantResults[0] == PackageManager.PERMISSION_GRANTED) {     //申请成功,进行相应操作     createFile("hello.txt");    } else {     //申请失败,可以继续向用户解释。    }    return;   }  } } 

到这里 runtime permissions 的权限申请操作就结束了,我们看一下效果:

浅谈Android 6.0之Runtime Permissions

允许后会再次调用createFile("hello.txt")方法,这次文件会被成功创建。

浅谈Android 6.0之Runtime Permissions

总结

其实还有一些内容需要写,这里先//TODO一下,希望以上内容对你有所帮助。

正文到此结束
Loading...