棉花糖运行时权限
从棉花糖开始,Android系统引入了新的权限机制,即本文要讲的运行时权限。
何为运行时权限呢?举个栗子,以某个需要拍照的应用为例,当运行时权限生效时,其Camera权限不是在安装后赋予,而是在应用运行的时候进行请求权限(比如当用户按下”相机拍照“按钮后)看到的效果则是这样的
接下来,对于Camera权限的处理完全权交给用户。是不是有点像苹果系统的处理呢,不要说这是抄袭,暂且称为师夷长技以制夷。
权限的分组
Android中有很多权限,但并非所有的权限都是敏感权限,于是6.0系统就对权限进行了分类,一般为下述几类
- 正常(Normal Protection)权限
- 危险(Dangerous)权限
- 特殊(Particular)权限
- 其他权限(一般很少用到)
正常权限
正常权限具有如下的几个特点
- 对用户隐私没有较大影响或者不会打来安全问题。
- 安装后就赋予这些权限,不需要显示提醒用户,用户也不能取消这些权限。
正常权限列表
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
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
UNINSTALL_SHORTCUT
上述的权限基本设计的是关于网络,蓝牙,时区,快捷方式等方面,只要在Manifest指定了这些权限,就会被授予,并且不能撤销。
特殊权限
这里讲特殊权限提前讲一下,因为这个相对来说简单一些。
特殊权限,顾名思义,就是一些特别敏感的权限,在Android系统中,主要由两个
- SYSTEM_ALERT_WINDOW,设置悬浮窗,进行一些黑科技
- WRITE_SETTINGS 修改系统设置
关于上面两个特殊权限的授权,做法是使用startActivityForResult
启动授权界面来完成。
请求SYSTEM_ALERT_WINDOW
private static final int REQUEST_CODE = 1;
private void requestAlertWindowPermission() {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (Settings.canDrawOverlays(this)) {
Log.i(LOGTAG, "onActivityResult granted");
}
}
}
上述代码需要注意的是
- 使用Action
Settings.ACTION_MANAGE_OVERLAY_PERMISSION
启动隐式Intent - 使用
"package:" + getPackageName()
携带App的包名信息 - 使用
Settings.canDrawOverlays
方法判断授权结果
请求WRITE_SETTINGS
private static final int REQUEST_CODE_WRITE_SETTINGS = 2;
private void requestWriteSettings() {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_WRITE_SETTINGS) {
if (Settings.System.canWrite(this)) {
Log.i(LOGTAG, "onActivityResult write settings granted" );
}
}
}
上述代码需要注意的是
- 使用Action
Settings.ACTION_MANAGE_WRITE_SETTINGS
启动隐式Intent - 使用
"package:" + getPackageName()
携带App的包名信息 - 使用
Settings.System.canWrite
方法检测授权结果
注意:关于这两个特殊权限,一般不建议应用申请。
危险权限
危险权限实际上才是运行时权限主要处理的对象,这些权限可能引起隐私问题或者影响其他程序运行。Android中的危险权限可以归为以下几个分组:
- CALENDAR
- CAMERA
- CONTACTS
- LOCATION
- MICROPHONE
- PHONE
- SENSORS
- SMS
- STORAGE
各个权限分组与其具体的权限,可以参考下图:
PS:开发者最好把是否授权那个提示框的不再显示去掉,也就是说重写那个是否授权的提示框,如果不那样做,会导致你的APP的界面静止不动,很有可能会崩溃。
当然事情不是绝对的,你还可以告诉用户,他虽然点了不再显示拒绝的,他还可以进入设置,同意那个权限,如果用户再次在设置里边禁止那个权限,那么再次进入APP,系统还是会提示是否授权的,也就是说
第一次打开APP-->拒绝权限,并且点了不在提示-->用户打开设置-->同意该项权限-->用户在设置里边再次禁止权限-->打开APP-->系统还是会提示是否授权