Android6.0权限动态申请

        如今的手机操作系统已经到了8.0,早在6.0的时候就有了权限的动态申请,危险的权限在使用到的时候动态申请。比如相机权限、读写权限等。

需要动态申请的危险权限有

READ_CALENDARWRITE_CALENDAR

CONTACTSREAD_CONTACTS ,WRITE_CONTACTS, GET_ACCOUNTS

ACCESS_FINE_LOCATION , ACCESS_COARSE_LOCATION

MICROPHONERECORD_AUDIO

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

SEND_SMS RECEIVE_SMS , READ_SMS RECEIVE_WAP_PUSH , RECEIVE_MMS

READ_EXTERNAL_STORAGE , WRITE_EXTERNAL_STORAGE

CAMERA

        这些权限在使用的时候需要现在AndroidManifest声明,然后在使用到的时候动态申请。接下来说一下我在使用中遇到的问题。

        最近做的项目中用到了读写sd卡和相机的权限,之前做的都是把targetSdkVersion定在23以下,越过动态权限配置部分,这样总归不是个办法,所以在网上寻找动态权限配置的方法。找了一些也试了一些,但是在小米3上总归不是很完美。我的实现思路如下如下:

        在程序启动的时候检查是否有对应的权限(我这里是读写和相机的权限),如果有权限则程序继续执行相应的代码,如果没有权限则提示询问用户是否授权,如果用户选择授权则继续执行相应的代码,如果用户选择了否且没有勾选不在提示则再次询问用户是否授权,知道用户授权才可登陆。如果用户选择了不授权并且勾选了不在提示,则提示用户去设置中开启对应的权限,如果用去开启并且开始了全部权限,用户再次登陆会直接接入到程序,如果选择了不开启则退出程序。

        可是我在实现的手发现,第一次启动程序的时候提示用户授权没有问题,但是如果用户选择了否的话就不会弹出系统的提示框了,但是会走onRequestPermissionsResult()回调方法,根据shouldShowRequestPermissionRationale()方法来判断还是不行,最后实在没办法了就直接略掉了中的再次弹出提示框的部分,用户拒绝授权之后就直接弹出提示框让用户到设置中去开启对应的权限,只有用户把所有的权限都开启之后才可以登陆,否则每次启动都会提示。

下面贴出实现方法和简略效果图:

        首先是公共类:

public classPermissionsUtil {

// 状态码、标志位

public static final intREQUEST_STATUS_CODE=0x001;

public static final intREQUEST_PERMISSION_SETTING=0x002;

//常量字符串数组,将需要申请的权限写进去,同时必须要在Androidmanifest.xml中声明。

public staticString[]PERMISSIONS_GROUP_SORT= {

Manifest.permission.WRITE_EXTERNAL_STORAGE,

Manifest.permission.CAMERA

};

private staticPermissionCallbackscallbacks;

public interfacePermissionCallbacks {

voidonPermissionsGranted();//权限都有

voidonPermissionsDenied(intrequestCode, List perms);

}

public static voidcheckAndRequestPermissions(finalActivity activity, PermissionCallbacks callback) {

callbacks= callback;

if(Build.VERSION.SDK_INT>=23) {

// 一个list,用来存放没有被授权的权限

ArrayList denidArray =newArrayList<>();

// 遍历PERMISSIONS_GROUP,将没有被授权的权限存放进denidArray

for(String permission :PERMISSIONS_GROUP_SORT) {

intgrantCode = ActivityCompat.checkSelfPermission(activity, permission);

if(grantCode == PackageManager.PERMISSION_DENIED) {

denidArray.add(permission);

}

}

// 如果该字符串数组长度大于0,说明有未被授权的权限

if(denidArray.size() >0) {

//循环处理所有未授权的权限,每次只添加一个权限进行获取

ArrayList denidArrayNew =newArrayList<>();

denidArrayNew.add(denidArray.get(0));

// 将denidArray转化为字符串数组,方便下面调用requestPermissions来请求授权

String[] denidPermissions = denidArrayNew.toArray(newString[denidArrayNew.size()]);

requestPermissions(activity, denidPermissions);

}else{

//已授权

callbacks.onPermissionsGranted();

}

}else{

callbacks.onPermissionsGranted();

}

}

/**

* 关于shouldShowRequestPermissionRationale函数的一点儿注意事项:

* ***1).应用安装后第一次访问,则直接返回false;

* ***2).第一次请求权限时,用户Deny了,再次调用shouldShowRequestPermissionRationale(),则返回true;

* ***3).第二次请求权限时,用户Deny了,并选择了“dont ask me again”的选项时,再次调用shouldShowRequestPermissionRationale()时,返回false;

* ***4).设备的系统设置中,禁止了应用获取这个权限的授权,则调用shouldShowRequestPermissionRationale(),返回false。

*/

public static booleanshowRationaleUI(Activity activity, String permission) {

returnActivityCompat.shouldShowRequestPermissionRationale(activity, permission);

}

/**

* 对权限字符串数组中的所有权限进行申请授权,如果用户选择了“dont ask me again”,则不会弹出系统的Permission申请授权对话框

*/

public static voidrequestPermissions(Activity activity, String[] permissions) {

ActivityCompat.requestPermissions(activity, permissions,REQUEST_STATUS_CODE);

}

/**

* 用来判断,App是否是首次启动:

* ***由于每次调用shouldShowRequestPermissionRationale得到的结果因情况而变,因此必须判断一下App是否首次启动,才能控制好出现Dialog和SnackBar的时机

*/

public static booleanisAppFirstRun(Activity activity) {

if(PreferencesUtils.getBoolean(activity,"first_run",true)) {

PreferencesUtils.putBoolean(activity,"first_run",false);

return true;

}else{

PreferencesUtils.putBoolean(activity,"first_run",false);

return false;

}

}

}

然后再启动页执行如下代码:

PermissionsUtil.checkAndRequestPermissions(this,object: PermissionsUtil.PermissionCallbacks{

override funonPermissionsGranted() {

dosomething()

}

override funonPermissionsDenied(requestCode: Int, perms: MutableList?) {

}

})

当然回调是必不可少的

override funonRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray){

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

if(requestCode == PermissionsUtil.REQUEST_STATUS_CODE) {

if(permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {//读写权限

if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {//同意

PermissionsUtil.checkAndRequestPermissions(this,object:PermissionsUtil.PermissionCallbacks{

override funonPermissionsGranted() {

dosomething()

}

override funonPermissionsDenied(requestCode: Int, perms: MutableList?) {

}

});//请求

}else{//不同意

createLoadedAlertDialog("在设置-应用-"+ getString(R.string.app_name) +"-权限中开启存储空间权限,以正常使用App功能");

}

}

if(permissions[0].equals(Manifest.permission.CAMERA)) {//相机权限

if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {//同意

PermissionsUtil.checkAndRequestPermissions(this,object:PermissionsUtil.PermissionCallbacks{

override funonPermissionsGranted() {

dosomething()

}

override funonPermissionsDenied(requestCode: Int, perms: MutableList?) {

}

});

}else{//不同意

createLoadedAlertDialog("在设置-应用-"+ getString(R.string.app_name) +"-权限中开启电话权限,以正常使用App功能");

}

}

}

}

每个权限都单独做了处理,避免没有权限进入会崩溃。

下面是项目运行截图:


第一次登陆弹出系统提示框,询问用户是否授权


用户选择拒绝后弹出用户去设置的弹框,如果用户选择设置并且去开启了相应的权限则用户再次登陆进入程序,如果用户点击取消则退出程序,用户再次进入还会弹出弹框,逻辑与上面相同。

结语:由于没怎么写过类似的文章在逻辑上还有很多地方写的不是很好,请大家多多指点。有问么疑问提出来大家一起探讨。

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

推荐阅读更多精彩内容