Android-6.0 棉花糖权限的那点事

Android6.0引入了全新的权限管理方式,也就是运行时权限,至于什么是运行时权限,我们先看一下6.0以前的权限处理。

6.0以前的权限

6.0以前的系统,我们在安装一个应用的时候会默认赋予所有权限。

pre-marshmallow-permission.jpg

安装的时候会提示应用需要获取的所有权限,选择安装则会全部获取,如果要拒绝获取权限,只能放弃安装应用。用户无法选择获取或者放弃某些权限。

6.0的运行时权限

什么是运行时权限?举个栗子,以某个需要拍照的应用为例,当运行时权限生效时,其Camera权限不是在安装后赋予,而是在应用运行的时候进行请求权限(比如当用户按下”相机拍照“按钮后)看到的效果则是这样的,提示用户需要权限,用户选择允许,才能获取到该权限。

marshmallow-permission.png

一个问题:我们必须要支持运行时权限吗?

如果我们不想启用运行时权限其实很简单,我们只要,把targetSdkVersion设置为设置低于23就可以了,系统会认为我们的应用还不支持新特性,会按照棉花糖以前的版本进行处理。这样的处理不会有任何的问题,但有一点,棉花糖对每一个应用都有一个权限管理界面,是这样

6a195423jw1ezwqnmjhcdj20u01hc40k.jpg

如果用户手动关闭了我们应用的某些权限,问题就出现了,运行应用时可能会出现崩溃。下面这个例子

TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String deviceId = telephonyManager.getDeviceId();
if (deviceId.equals(mLastDeviceId)) {//This may cause NPE
//do something
}

如果用户撤消了获取DeviceId的权限,那么再次运行时,deviceId就是null,如果程序后续处理不当,就会出现崩溃。所以说该来的还是要来的,我们需要处理好运行时权限问题。

权限分类

android系统的权限很多但不是所有的权限都是敏感权限,棉花糖将android系统权限分为四类。

1.正常权限(Normal Protection)

2.危险权限(Dangerous)

3.特殊权限(Particular)

4.其他权限(几乎使用不到)

1.正常权限

这一类权限是对用户隐私影响较小,没有什么安全问题,这类权限会像6.0以前的系统一样,安装就获取到这些权限,没有用户提醒,也不能被取消。下面是正常权限列表。

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中指定,应用安装就会获取。

2.危险权限

危险权限才是运行时权限的主要处理对象,这些权限可能会有隐私问题,或者影响其他应用的运行,危险权限可以分为以下几组:

  • CALENDAR
  • CAMERA
  • CONTACTS
  • LOCATION
  • MICROPHONE
  • PHONE
  • SENSORS
  • SMS
  • STORAGE

对于各组权限对应的具体权限如下:

6a195423jw1ezwpc11cs0j20hr0majwm.jpg

关于权限我们需要下面几个API

  • int checkSelfPermission(String permission) 用来检测应用是否已经具有权限
  • void requestPermissions(String[] permissions, int requestCode) 进行请求单个或多个权限
  • void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)

请求Camera的权限

private static final int REQUEST_PERMISSION_CAMERA_CODE = 1;
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!(checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
Toast.makeText(this, "Please grant the permission this time", Toast.LENGTH_LONG).show();
}
requestCameraPermission();
}
}
}
private void requestCameraPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA_CODE);
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CAMERA_CODE) {
int grantResult = grantResults[0];
boolean granted = grantResult == PackageManager.PERMISSION_GRANTED;
Log.i(LOGTAG, "onRequestPermissionsResult granted=" + granted);
}
}

通常情况下,我们会得到这样的一个对话框

marshmallow-permission.png

我们可以在onRequestPermissionsResult中获取用户的选择情况进行相应的处理。但如果用户选择了否,我们再次申请的时候就会多一个checkbox

6a195423jw1ezwtz1ljjgj20u01hcad8.jpg

如果用户选择了不在询问,然后拒绝,我们的应用基本上就获取不到这个权限了,shouldShowRequestPermissionRationale这个API可以帮我们判断接下来的对话框是否包含”不再询问“选择框,我们可以这样使用。这样如果我们第一次申请权限失败后,在申请权限的时候就会弹出提示Toast,这个使用一定要向用户说明我们为什么要申请这个权限,来做什么。

if (!(checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED)) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
Toast.makeText(this, "Please grant the permission this time", Toast.LENGTH_LONG).show();
}
requestReadContactsPermission();
} else {
Log.i(LOGTAG, "onClick granted");
}

对于同时申请多个权限我们可以

String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE};
requestPermissions(permissions, REQUEST_CODE);

效果是这样,同时申请多个权限可以避免弹出多个对话框造成不好的视觉影响。

6a195423jw1ezxulzbeu2j20iq0ggt9y.jpg

3.特殊权限

特殊权限是指特别敏感的权限,这里主要是指两个。

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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
Log.i("AlertWindowPermission", "onActivityResult granted");
}
}
}
}

需要注意:

  • 使用Action Settings.ACTION_MANAGE_OVERLAY_PERMISSION启动隐式Intent
  • 使用"package:" + getPackageName()携带App的包名信息
  • 使用Settings.canDrawOverlays方法判断授权结果

WRITE_SETTINGS 使用的则是 Action Settings.ACTION_MANAGE_WRITE_SETTINGS,使用Settings.System.canWrite方法检测授权结果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容