6.0权限申请巧遇问题

来源:互联网 发布:千岸科技有限公司知乎 编辑:程序博客网 时间:2024/05/16 00:55

小序

原本以为这次项目完成得不错,结果测试妹子在禅道上又提了些BUG,大多涉及到6.0权限的问题。这就比较尴尬了,毕竟是一开始并没有顾虑的。而关于权限申请,其实际上已经有很多前辈提供过相应的解决办法,在此谢过。

正文

1. 需动态申请的权限

权限的申请依据谷歌的分类来讲,一类属于普通的权限申请,与往常一样可直接在 AndroidManifest.xml 注册就可以了;另一类则需要在应用程序使用的地方执行动态申请,该类权限属危险权限(组),当然前提也得先在 AndroidManifest.xml 下注册声明。这里仅罗列需要动态申请的权限内容(摘自这里)。

权限组 权限 CALENDAR 日历 android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR CAMERA 相机 android.permission.CAMERA CONTACTS 联系人 android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS LOCATION 位置 android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION MICROPHONE 麦克风 android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
com.android.voicemail.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS PHONE 电话 android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
com.android.voicemail.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS SENSORS 传感器 android.permission.BODY_SENSORS SMS 短信 android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_CELL_BROADCASTS STORAGE 存储 android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE

2. 具体实现

了解完需要申请的权限之后,需要根据实际项目当中需要用到的相关权限,在相应的位置开始我们的权限申请。申请过程主要包括以下两个操作,另外也有人封装了些简单易用的依赖库,有兴趣的亲也可了解下。

/** * 以定动态申请位权限为例 */public void handPermission() {    // 定位权限组    String[] mPermissionGroup = new String[]{            Manifest.permission.ACCESS_FINE_LOCATION,            Manifest.permission.ACCESS_COARSE_LOCATION};    // 过滤已持有的权限    List<String> mRequestList = new ArrayList<>();    for (String permission : mPermissionGroup) {        if ((ContextCompat.checkSelfPermission(getActivity(), permission)                != PackageManager.PERMISSION_GRANTED)) {            mRequestList.add(permission);        }    }    // 申请未持有的权限    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !mRequestList.isEmpty()) {        ActivityCompat.requestPermissions(mActivity, mRequestList.toArray(                new String[mRequestList.size()]), 100);    } else {        // 权限都有了,就可以继续后面的操作    }}
/** * 回调权限申请结果 * * @param requestCode * @param permissions * @param grantResults */@Overridepublic void onRequestPermissionsResult(        int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {    super.onRequestPermissionsResult(requestCode, permissions, grantResults);    switch (requestCode) {        case 100: {            if (grantResults.length > 0                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                // 同意权限申请,就可以继续后面的操作            } else {                // 拒绝权限申请,提示申请权限的重要性            }        }        break;    }}

3. 巧遇问题

a. 反复申请

“重复申请”是不合理的,这样会严重影响到用户的体验。最好是在用户拒绝权限的申请用给予用户用好提示,或本次应用开启权限仅申请一次,不通过提示为授权之类的。

部分机子系统需要特别注意,因为它们整个应用的申请仅提示一次,如最为熟悉的小米/红米。无论之后再怎么requestPermissions也无济于事,到头来还得提示用户到应用设置手动启动权限。这算是比较恶心的一个事情,且其他机子上如果用户勾选了不再提示也是一样的。

建议权限申请不要再onResume()的生命周期中执行,因为权限申请操作后会再次调用onResume(),个人在小米/红米机子上测试出现过该问题。

b. 多权限申请带来的问题

String[] mPermissionGroup = new String[]{            Manifest.permission.CAMERA            Manifest.permission.ACCESS_COARSE_LOCATION};// 注意:这样的多权限申请是存在问题的if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {        ActivityCompat.requestPermissions(mActivity, mPermissionGroup, 100);    }

如上面所见,我定义了一个需要权限请求的数组。里面包括了两个权限组,一个是照相机的权限,另一个则是定位的权限(权限组当中的任意成员被授予权限,相当于权限组内的各个权限都将被授予权限)。那么在实际执行当中会是什么效果呢?

多权限申请效果1

经上面图示效果可以看到,多权限申请的时候每一个权限组的申请都被单独开来了。那么问题来了,因为权限的申请是我们主动发出的,并且一个应用当中往往不止一个地方需要权限申请。简单的说如果你已经执行百度定位授予了定位权限了。那么你下次就应该先判断定位权限是否已被授权再加入到多权限申请单中。

那么有人就要问了,即使一开始不判断是否授权。在申请授权的回调过程中不也能自己判断麽?嗯,确实是这样没错。但那只是针对mPermissionGroup这个整体,即如果当中有部分权限已经被授予,而剩下的未授予,将全部被重新申请

E/SQLiteDatabase: Failed to open database ‘/storage/emulated/0/emlibs/libs/monitor.db’
E/SQLiteDatabase: Failed to open database ‘/storage/emulated/0/baidu/tempdata/ls.db’

以上列举两种异常,主要在小米/红米机子上测试出现,其他机子未测试确认。出现该问题的罪魁祸首就是,在多权限申请当中将原已授权的权限拒绝了,且该权限刚好正被使用。解决以上原因只需要一步“过滤”,遍历mPermissionGroup集合当中每个成员的授权状态再执行多权限申请(如第2点当中写到的)

0 0