权限检查(一)

权限问题一直是Android开发人员很头疼的问题,比如经常会碰到朋友抱怨,这个录音权限判断不了或者是判断了没效果,只能另辟蹊径。其实我们开发过程中很容易碰到这些问题,但是这些问题都很零碎,所以也引不起大的注意,但是却容易发生一些意外状况.当然今天的主题是M版本的权限问题,这个问题阻拦了很多应用SDK升级23之路。就我自己的研究来看,我有好几个朋友未升级的理由都是,M版本的权限检查太恶心了,我们里面有那么多地方用到,改的很费劲,那么究竟如何呢?大家如果可以翻墙的话,可以去看看http://developer.android.com/intl/zh-cn/about/versions/marshmallow/android-6.0-changes.html这篇文档,里面着重提到了权限检查的问题。

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

一个Android应用默认情况下是不拥有任何权限的, 这即是说, 在默认情况下, 一个应用是没有权利去进行一些可能会造成不好影响的操作的. 这些不好的影响可能是对其它应用,操作系统,或者是用户。

如果应用需要一些额外的能力,则它需要在AndroidManifest.xml中静态地声明相应的权限。
 
如果应用没有在manifest中声明权限, 却使用了相应的功能, 在调用到相应功能的时候, 将会抛出异常。
比如程序要发送一个请求,却忘记加Internet权限, 那么在发送这个请求的时候程序就会抛出异常,一般不会catch这个异常,所以程序直接就崩溃了:
Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
 
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


其实我们大部分开发过程中的需求都是需要使用到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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值