权限检查(二)

权限检查(二)


我是插入的:推荐权限检查第三方 https://github.com/jsmeli/PermissionCheck ,望多多支持,感激不尽


1.问题

权限问题一直是android开发人员很头疼的问题,比如经常会碰到朋友抱怨,这个录音权限判断不了或者是判断了没效果,只能另辟蹊

径。其实我们开发过程中很容易碰到这些问题,但是这些问题都很零碎,所以也引不起大的注意,但是却容易发生一些意外状况.当然

今天的主题是M版本的权限问题,这个问题阻拦了很多应用sdk升级23之路。就我自己的研究来看,我有好几个朋友未升级的理由都

是,M版本的权限检查太恶心了,我们里面有那么多地方用到,改的很费劲,那么究竟如何呢?大家如果可以翻墙的话,可以去看看

下面这篇文档,里面着重提到了权限检查的问题。

http://developer.android.com/intl/zh-cn/about/versions/marshmallow/android-6.0-changes.html


2.概述

一个Android应用默认情况下是不拥有任何权限的, 这即是说, 在默认情况下, 一个应用是没有权利去进行一些可能会造成不好影响的操

作的. 这些不好的影响可能是对其它应用,操作系统,或者是用户。如果应用需要一些额外的能力,则它需要在AndroidManifest.xml中静

态地声明相应的权限。如果应用没有在manifest中声明权限, 却使用了相应的功能, 在调用到相应功能的时候, 将会抛出异常。

for example:

比如程序要发送一个请求,却忘记加Internet权限, 那么在发送这个请求的时候程序就会抛出异常,一般不会catch这个异常,所以程序直接

就崩溃了:

caused by: java.lang.securityexception: permission denied (missing internet permission?)

3.权限分组

在Android 6.0 (API 23) 发布之前, 所有的权限都在安装应用的时候显示给用户,用户选择安装则表示全部接受这些权限, 之后无法撤销

对这些权限的授权。Android 6.0开始, 一部分比较危险的权限需要在程序运行时显式弹框,请求用户授权。至于什么时候弹这个框,由应

用程序自己决定。对于其他权限,认为不是很危险,所以仍然保持原来的做法,在用户安装应用程序时就予以授权。还需要注意的是,在设

置中,对于应用的危险权限,用户可以选择性地进行授权或者关闭。当然,在我们开发过程中其实注意两类就够了,一种就是直接可以申

请的,另一种就是需要手动检查的,也就说涉及到隐私的权限。

直接申请的权限列表(Normal权限):

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

需要进行检查的组(Dangerous权限)

CALENDAR

CAMERA

CONTACTS

LOCATION

MICROPHONE

PHONE

SENSORS

SMS

STORAGE
感觉配图效果更好


4.问题解决方案

其实我们大部分开发过程中的需求都是需要使用到Dangerous权限,为啥呢,因为产品经理的需求,产品想要的数据基本或多或少都

会涉及到用户的一些隐私信息,所以苦逼的还是我们这些开发人员…….

权限检查的代码网上其实都大同小异,基本都是那么写的(以通讯录权限为例):

//动态获取权
    if (checkSelfPermission(Manifest.permission.READ_CONTACTS) !=   PackageManager .PERMISSION_GRANTED) {
        if (!ActivityCompat.shouldShowRequestPermissionRationale(context, Manifest.permission.READ_CONTACTS)) {
            //这种情况是该用户已经选择了不再提示的选项,需要手动给该用户做提示操作
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission .READ_CONTACTS},PERMISSION_REQUEST);
        }
    } else {
        //获取通讯录信息
        Intent intent = new Intent(Intent.ACTION_PICK,ContactsContract.Contacts.CONTENT_URI);
        startActivityForResult(intent, CHOOSE_CONTACT);
    }

如果没有权限并且进行了申请,那么是会有回调结果的

权限申请后的回调:

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[]
    grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case PERMISSION_REQUEST:
                if (grantResults.length > 0 && grantResults[0] == PackageManager
                        .PERMISSION_GRANTED) {
                    //获取通讯录信息
                    Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts
                            .CONTENT_URI);
                    startActivityForResult(intent, CHOOSE_CONTACT);
                }
                break;
        }
    }

这就是一套正常流程了,看着是没有毛病的,但是我试了其他的手机,就有了问题了,联想的ZUK Z2手机,无论权限禁止与否,

checkSelfPermission(Manifest.permission.READ_CONTACTS)

该方法返回值都是0,也就是说默认是一直都有权限,那么就有问题了这样走的是有权限的流程,就直接打开通讯录了,其实这时候权

限是禁止的找了各种资料发现6.0以下的手机都会返回0,这个问题好像有点眉目了,我就检查了代码还真是少了这个判断,那么我就

又开始各种修改,觉得找到了问题的关键了,修改后

    //动态获取权限
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager
                .PERMISSION_GRANTED) {
            if (!ActivityCompat.shouldShowRequestPermissionRationale(context,
                    Manifest.permission.READ_CONTACTS)) {
                //这种情况是该用户已经选择了不再提示的选项,需要手动给该用户做提示操作
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission
                        .READ_CONTACTS}, PERMISSION_REQUEST);
            }
        } else {
            //获取通讯录信息
            Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
            startActivityForResult(intent, CHOOSE_CONTACT);
        }
    }

运行后结果

这就不对了,怎么会酱紫,这就不科学了,完全没有道理。

手机相关权限:

手机型号:

一看也确实是6.0.1的系统,这就比较无解了,那么碰上这种手机如何处理呢?个人处理方式,就通讯录来说的话,该手机的现象是即

使权限禁止,也能打开通讯录,因为代码判断拦不住,居然也能调用成功,但是回传联系人的时候使用ContentProvider读取时候就

报异常了,所以为了满足需求,这边做了以下的处理,如果捕获到异常,弹出自定义的提示框,让用户去授予权限。

try{
    //读取通讯录过程
    }catch(Exception e){
        //捕获到异常就做处理
    }

ps:授予权限的快捷键,最好是跳到设置里面的应用程序列表(附上代码)

Intent intent = new Intent(Settings.ACTION_APPLICATION_SETTINGS);
startActivity(intent);

如果有碰到这样问题的同学欢迎讨论,思想总是在碰撞中产生火花。
个人邮箱: jsmeli@163.com

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值