Android学习之相机权限适配问题详解

本文和大家分享的主要是android 相机权限适配中常见的一些坑,一起来看看吧,希望对大家 学习android有所帮助。

我们都知道,google 在 6.0 以后加强了应用权限的管理,我们也能通过标准的方法去申请权限,但是由于一些厂商的修改,在适配过程中我们会遇到各种各样的问题。在 6.0 之前,也可能会因为用户的一些设置导致我们无法获取权限。

6.0以下系统

·  打开系统相机常规来说不需要相机权限。但是如果手机 root 了,并且使用获得 root 权限 ( 未获取 root权限设置不起作用 ) 的安全管理(如 LBE ,开启主动防御后)软件管理权限,此时就会出现一些问题。比如:在我们的软件调用系统相机拍照时,这些安全管理的软件会拦截这个请求,然后根据我们的设置(第一次请求时一般弹窗询问)允许、询问或者拒绝权限,此时如果是拒绝了,我们将无法调用系统相机!而此时如果用户勾选了记住选择并拒绝,那么我们将无法调用系统相机并且在下一次请求时没有任何提示!

·  由于扫描二维码不是常规的打开系统的相机界面,所以就算是在 6.0 以下也要判断权限,一般通过如下方法判断是否拥有相机权限

/**

*  通过尝试打开相机的方式判断有无拍照权限(在 6.0 以下使用拥有 root 权限的管理软件可以管理权限)

*

*  @return

*/

public  static boolean cameraIsCanUse() {

boolean isCanUse =  true;

Camera mCamera =  null;

try {

mCamera = Camera.open();

Camera.Parameters mParameters = mCamera.getParameters();

mCamera.setParameters(mParameters);

}  catch ( Exception e) {

isCanUse =  false;

}

if (mCamera !=  null) {

try {

mCamera.release();

}  catch ( Exception e) {

e.printStackTrace();

return isCanUse;

}

}

return isCanUse;

}

·  根据上面的代码,我们想是不是可以用来解决问题一。因为通过调用以上代码,如果无法打开相机 (返回 false) 则说明没有了相机权限。

·  但是,在测试过程中发现, LBE 如果开启了主动防御,能正确的控制权限,但是没有开启主动防御,任凭你怎么设置权限都是没用的,就算你在 LBE 中拒绝了相机权限但还是能打开系统相机的(也就是说没有开启主动防御这些设置是不生效的,不知道为什么还允许用户设置)!

·  而且,如果关闭了 LBE 的主动防御再去应用调用相机,虽然上面的代码会返回 false ,但是,这时候还是可以调用系统相机的!

·  综上,在 6.0 以下系统,我们可以选择这样做,在调用二维码的地方使用上述代码去判断是否能打开相机,调用系统相机界面拍照则无需判断(因为只有 root 过的手机才能拦截这个请求),如果用户 root 过,我们没法得到正确的判断,所以只能选择放弃了!

6.0及以上系统

·6.0 开始,应用中使用敏感权限需要通过用户的允许,所以,我们需要下面这样一个工具类来获取权限(直接上代码,代码中有解释):

/**

*  从 fragment 检查权限,如果传入的 fragment 是 null ,则后面请求权限时会调用 ActivityCompat

*  的方法

*

*  检查 6.0 及以上版本时,应用是否拥有某个权限,拥有则返回 true ,未拥有则再判断上次

*  用户是否拒绝过该权限的申请(拒绝过则 shouldShowRequestPermissionRationale 返回

* true—— 这里有些手机如红米 ( 红米  pro) 永远返回  false

*  这里的处理是弹一个对话框引导用户去应用的设置界面打开权限,返回 false 时这里执行

* requestPermissions 方法,此方法会显示系统默认的一个权限授权提示对话框,并在

* Activity 或 Fragment 的 onRequestPermissionsResult 得到回调,注意方法中的 requestCode

*  要与此处相同)

*

* @param fragment :如果 fragment 不为 null 则调用 fragment 的方法申请权限(因为有些手机

*  上在 Fragment 调用 ActivityCompat 的 方法申请权限得不到回调,例如红米手机)

* @param activity :用于弹出提示窗和获取权限

* @param permission :对应的权限名称,如: Manifest.permission.CAMERA

* @param hint :引导用户进入设置界面对话框的提示文字

* @param requestCode :请求码,对应 Activity 或 Fragment 的 onRequestPermissionsResult

*  方法的 requestCode

* @return : true- 拥有对应的权限  false :未拥有对应的权限

*/

public  static boolean checkPermission(Fragment fragment,  final Activity activity, String permission,

String hint, int requestCode) {

// 检查权限

if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {

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

// 显示我们自定义的一个窗口引导用户开启权限

showPermissionSettingDialog(activity, hint);

}  else {

// 申请权限

if (fragment ==  null) {

ActivityCompat.requestPermissions(activity,

new String[]{permission},

requestCode);

}  else {

fragment.requestPermissions(

new String[]{permission},

requestCode);

}

}

return  false;

}  else {  // 已经拥有权限

return  true;

}

}

·  通过注释我们也可以看到,在一些手机上如果按照 google 的写法,也会出现一些问题。但是在测试过程中使用模拟器并没有出现这样的问题。

·  问题 1 :在模拟器上,无论在 activity 还是 Fragment 中,调用 ActivityCompat.requestPermissions 去申请权限都能得到回调。而在小米手机上,如果在 Fragment 中调用申请权限的方法,必须使用 Fragment 的requestPermissions 方法去申请权限才能在 Fragment 中得到回调。由于没有条件,所以只测试了红米手机 (红米  pro) ,其他手机暂时不清楚!

·  问题 2 :在小米上, shouldShowRequestPermissionRationale 始终返回 false

·  问题 3 :在应用运行的过程中,如果去系统的设置里面关闭了应用的某个权限,再回来应用时会闪退(前提是前面这个权限是使用过的)!可以参考我的另一篇文章解决: http://www.jianshu.com/p/8c08080220f1  ,测试过程发现,QQ 运行过程中,在设置界面手动关闭了他的某个界面,他竟不会重启,而且毫无卡顿,虽然微信没有显式的重启,但是在恢复界面过程中会有明显的卡顿,而支付宝则直接重启应用!

来源:简书

时间: 2024-11-10 08:47:49

Android学习之相机权限适配问题详解的相关文章

android学习之remote service 的aidl详解

写在前面的话: 关于remote service中使用aidl来实现跨进程,多线程通信,我是参考了三篇文章,大概把这个弄明白了. (1)android 官方关于aidl的说明文档 docs/guide/components/aidl.html (2)Android学习笔记23服务Service之AIDL和远程服务实现进程通信以及进程间传递自定义类型参数 http://blog.csdn.net/honeybaby201314/article/details/19989455 (3) Androi

Android学习笔记之RadioButton的使用详解

(1)选用radioGroup的图标 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

Android学习笔记:Activity生命周期详解

进行android的开发,必须深入了解Activity的生命周期.而对这个讲述最权威.最好的莫过于google的开发文档了. 本文的讲述主要是对 http://developer.android.com/training/basics/activity-lifecycle/index.html 的翻译,加上了个人的一些细节和补充. 一.总体介绍

Android学习笔记之GridView的使用详解

(1)创建布局代码如下: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" andr

Android 开发中的屏幕适配技术详解

Android屏幕适配问题详解

上篇-Android本地化资源目录详解 :http://www.cnblogs.com/stafen/p/3833048.html 单位: px(像素):屏幕上的点. in(英寸):长度单位. mm(毫米):长度单位. pt(磅):1/72英寸. dp/dip(与密度无关的像素):一种基于屏幕密度的抽象单位.在每英寸160点的显示器上,1dp = 1px,在大于160点的显示器上可能增大.一般用于位置和尺寸属性的单位. dpi:表示当前屏幕的密度. sp(与刻度无关的像素):主要用于字体大小单位

学习笔记——Maven settings.xml 配置详解

文件存放位置 全局配置: ${M2_HOME}/conf/settings.xml 用户配置: ${user.home}/.m2/settings.xml note:用户配置优先于全局配置.${user.home} 和和所有其他系统属性只能在3.0+版本上使用.请注意windows和Linux使用变量的区别. settings.xml详解 声明规范 <?xml version="1.0" encoding="UTF-8"?> <settings x

【Android】状态栏通知Notification、NotificationManager详解(转)

在Android系统中,发一个状态栏通知还是很方便的.下面我们就来看一下,怎么发送状态栏通知,状态栏通知又有哪些参数可以设置? 首先,发送一个状态栏通知必须用到两个类:  NotificationManager . Notification. NotificationManager :  是状态栏通知的管理类,负责发通知.清楚通知等. NotificationManager 是一个系统Service,必须通过 getSystemService()方法来获取. [java] view plainc

android四大基础组件--Service生命周期详解

android四大基础组件--ServiceService 生命周期详解 1.Service的生命周期: I> 在非绑定Service情况下,只有oncreate(),onStartCommand(),onDestory()方法情况下:  操作方法对应生命周期一: a.[执行startService(Intent)] 执行生命周期方法:oncreate()--->onStartCommand(): b.[执行stopService(Intent)] 执行生命周期方法:onDestory();