Android动态权限适配

最近APP里面要添加动态权限,网上找了不少例子并经过一定的测试,基本流程有了一定的认识,需要注意的地方记录下来以备以后查阅。

一 各大手机厂商的适配

依据各大手机Rom的不同表现,可以分为三种不同的模式:标准模式,默认开启模式,特殊权限模式。

1 标准模式:代表华为Mate8,三星S6。

基本流程如下:

用户启动APP后,第一次需要权限的时候,判断用户当前权限,弹出系统默认的系统Snacbar

intstate = ActivityCompat.checkSelfPermission(activity,requestPermission);

通过onRequestPermissionsResult判断出来用户选择结果,

用户选择始终允许,则直接获取了权限,APP继续后续流程。

如果用户选择了拒绝,则需要APP自己处理,一般会弹出一个Dialog 提示用户需要该权限,是否去设置里面打开该权限。拒绝也分为两种情况,一种是选择了禁止后不再询问,一种是没有选择。两种的区别在于在标准模式下,用户选择了禁止不再提问后,不会再弹出系统Snacbar,而是直接返回拒绝的结果,如果用户没有选择,则会继续弹出系统Snacbar。

用户启动权限申请后,会有shouldShowRequestPermissionRationale来判断是否需要APP弹出一个提示框,提示用户来同意申请该动态权限。这个在应用首次申请权限时,如果用户点击拒绝,下次再申请权限,Android允许你提示用户,你为什么需要这个权限,更好引导用户是否授权。

本来是添加一个自定义Dialog来提示用户,后产品认为提示过多,则默认还是直接去申请权限。

if(ActivityCompat.shouldShowRequestPermissionRationale(activity,requestPermission)) {

//为了优化用户关闭权限后 第一次没有任何提示

if(ConfigUtils.isHtc()) {

openSettingActivity(activity,activity.getString(R.string.permission_setting_head)

+ message +"权限",permissionGrant);

}else{

//TODO 直接进行权限申请 不再先进行自定义提示

ActivityCompat.requestPermissions(activity, newString[]{requestPermission},requestCode);

//                shouldShowRationale(activity, requestCode, requestPermission, permissionGrant);

}

}else{

ActivityCompat.requestPermissions(activity, newString[]{requestPermission},requestCode);

}

2 默认开启模式:代表HTC One。

和标准模式的区别,是调用检查APP权限的代码后,默认会给用户该权限。

所以不会弹出系统Snacbar提示你去进行选择,用户没有感觉到安装了一个动态权限版本的APP。

3 特殊权限模式:代表360手机。

360正常是属于默认开启模式的,但是针对特殊权限里面的部分权限,360认为是危险权限会进行自定义的提示。比如:照相机被认为是危险权限,打开本地存储则不属于。

针对危险权限的权限状态,返回的也是通过,但是360会自动打开自定义的Dialog,这个和系统默认的Snacbar是一个逻辑流程。

二  多权限处理

前提也是通过遍历,获取多个权限当前的状态,依据各自的权限状态再去分别处理。

多权限的返回结果:

比如 申请了三个权限A,B,C。A选择通过,B拒绝,C拒绝并不再提示,则在处理返回值的时候,需要分别处理,正常会弹出一个Dialog提示,B和C没有权限,需要到设置界面去打开。

等用户再次申请这三个权限的时候,肯定返回B和C需要申请,默认标准模式下会弹出系统Snacbar提示B权限的申请,而没有A和C,C已经拒绝提示,A已经通过。如果B通过了,则返回结果里面只有C没有通过,APP依然会弹出需要到设置界面去打开C权限的Dialog。

三 权限状态不准确的处理 代表HTC One

HTC属于默认申请就给权限的手机,但是用户在设置界面关闭了赋予APP的动态权限后,利用

intstate = ActivityCompat.checkSelfPermission(activity,requestPermission);

得到的仍在是已经有权限的结果,这样会造成APP的实际没有权限,而后续的使用权限的操作会导致APP崩溃。针对这种情况需要添加AppOps来判断当前的权限状况:

intstate = ActivityCompat.checkSelfPermission(activity,requestPermission);

if(state == PackageManager.PERMISSION_GRANTED) {

    // 避免此时是已经被拒绝造成的通过

    String appPermission =chageToAppOpsManagerC(requestCode);

    if(null!= appPermission) {

          checkResult =getPermissionState(activity,appPermission);

     }

}

private static int getPermissionState(Context activity,String  op) {

     if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.KITKAT) {

               AppOpsManager appOpsManager = (AppOpsManager)                     activity.getSystemService(Context.APP_OPS_SERVICE);

        returnappOpsManager.checkOpNoThrow(op,Binder.getCallingUid(),activity.getPackageName());

}

returnAppOpsManager.MODE_ALLOWED;

}

这时的返回值才是正确的状态。

备注:

动态权限优化了流程,原则就是只要有能弹出系统的Snacbar则就先弹Snacbar,不能弹出任何Snacbar之后,依据返回的结果APP给出提示需要什么权限,要跳转到系统设置里面赋予权限。



其他注意点

1 需要判断系统版本是否是6.0以上。低于6.0版本的不需要进行动态权限的判断,如果进入了动态权限的判断逻辑,则各种效果都会出来。

2 升级到6.0以上的版本编译之后,一些操作有了限制。比如,7.0之后对文件共享进行来限制,打开照相机,获取相机图片需要使用FileProvider进行操作。

if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {//7.0及以上

Uri contentUri =getUriForFile(mContext,"包名.fileProvider",

newFile(FileUtils.getSDCardRoot() + ConfigFile.CACHE_AVATAR_DIR,ConfigFile.CACHE_AVATAR_CAMERA_NAME));

intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,contentUri);

intentFromCapture.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION

| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

}else{

intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,Uri

.fromFile(newFile(FileUtils.getSDCardRoot() + ConfigFile.CACHE_AVATAR_DIR,ConfigFile.CACHE_AVATAR_CAMERA_NAME)));

}

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

推荐阅读更多精彩内容