Android 6.0动态权限申请
来源:互联网 发布:苹果版解压缩软件 编辑:程序博客网 时间:2024/06/10 22:07
Android 6.0运行时权限动态申请处理
最近需要在项目中对android 6.0以上的手机做权限处理,所以抽了个时间,将大于或等于6.0以上的权限处理做一个总结!
android 在6.0以后,将权限分为两类,分别为Normal Pemission和Dangerous Permission,Normal Permission不需要用户在操作的时候进行授权,例如最常用的访问网络的权限;Dangerous Permission 则不同,其涉及到了用户的隐私,必须在用户操作的过程中,进行授权通过了,才可以进行某些预定的操作,例如获取手机联系人,若用户没有对此进行授权,则会导致程序无法获取到手机上的联系人。而当用户拒绝该权限之后,没有在设置中将其打开,则会一直处于权限拒绝状态,所以,我们需要对此进行处理。
下面,将通过一个打电话的例子来演示操作。
在6.0以下的手机中,我们可以直接通过Intent的方式来拨打电话,代码如下:
private void call(){ Intent intent = new Intent(Intent.ACTION_CALL); Uri data = Uri.parse("tel:" + mPhone); intent.setData(data); startActivity(intent); }
而在6.0以上的手机中,我们则需要通过一些步骤,确定当前程序是否拨打电话的权限,如果有权限,则可以和如上方式一样直接调用call()方法来打电话,但是若检测到当前程序没有拨打电话的权限。那么,我们需要通过如下操作来进行处理:
1:申请用户授权拨打电话的权限2:若授予了该权限,则调用call()方法进行拨打电话3:若用户拒绝了,则我们需要进行一些其他的操作,来告诉用户,该功能不可用。
下面,我将具体的完整流程整理了下(画图技术太烂,不要在意,哈哈,希望大家都能看明白我画的是啥玩意儿 ^_^ ):
————————————-一条有逼格的分界线,下面开始撸码—————————————–
首先,先完成功能上的操作,具体代码如下,代码中,打了很多的Log,也写了很多注释,这样能让大家看的更清楚,明白!
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView();}private void initView(){ call = (TextView) findViewById(R.id.call); call.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //检查权限 checkPermission(); } });}private void checkPermission(){ //1:判断当前手机系统是否大于或等于6.0 //2:若大于6.0,则检查是否由打电话的权限 //3:若没有打电话的权限 则申请打电话的权限 //4:若有打电话的权限 则直接打电话 //5:若当前小于6.0,则直接打电话 if(Build.VERSION.SDK_INT >= M ){ Log.e(TAG,"版本大于等于6.0"); //checkSelfPermission方法用于检测程序是否含有某项权限 //参数一:当前的上下文对象 //参数二:需要检测的权限 /** * checkSelfPermission方法用于检测程序是否含有某项权限 * 参数一:当前的上下文对象 * 参数二:需要检测的权限 * * 该方法得返回值为int类型,有两种值,分别为: * 1:PackageManager.PERMISSION_DENIED 该权限被拒绝 * 2:PackageManager.PERMISSION_GRANTED 该权限被授予 */ int isPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.CALL_PHONE); if(isPermission == PackageManager.PERMISSION_GRANTED){ //该权限已被授予 Log.e(TAG,"该权限已被授予"); call(); }else{ Log.e(TAG,"该权限已被拒绝"); //申请权限 /** * ActivityCompat.requestPermissions()方法用于申请权限 * 参数一:Activity * 参数二:需要申请的权限,其为一个数组,可同时传入多个将要申请的权限 * 参数三:请求码,用于在请求完成之后的回调中使用 */ ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},REQUEST_CODE); } }else { call(); }}private void call(){ Intent intent = new Intent(Intent.ACTION_CALL); Uri data = Uri.parse("tel:" + mPhone); intent.setData(data); startActivity(intent);}/** * 该方法即为申请权限的回调方法 无论申请成功或者失败 都会回调这个函数 * @param requestCode 上文中提到的请求码 * @param permissions 申请的权限 * @param grantResults 申请的结果 */@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode == REQUEST_CODE){ if(grantResults != null && grantResults.length>0){ if(grantResults[0] == PackageManager.PERMISSION_GRANTED){ Log.e(TAG,"权限已被授予,此时可以拨打电话了"); call(); }else{ Toast.makeText(this,"您拒绝了拨打电话的权限!",Toast.LENGTH_SHORT).show(); } } }}
到此 动态权限的功能也就处理完毕了!
你以为我会说结束了么,哈哈哈,想多了吧,老铁!^_^
不知道读到这里,大家有没有一个问题:难道我一涉及到危险权限的操作,就要写这么多代码来处理吗?这样会不会很丧心病狂啊!
下面,高大上的东西来了:封装一个高大上的权限申请框架!
写博客之前,也看了好些技术求人的方案,最终选择的是一个注解 + 反射的方案来处理
下面直接贴代码,注释已经很详细了,相信大家能看明白!
PermissionHelper:权限问题集中在此处理
package com.justh.dell.util;import android.app.Activity;import android.app.Fragment;import android.support.v4.app.ActivityCompat;import java.util.ArrayList;import static com.justh.dell.util.PermissionUtils.getDeniedPermissions;/** * Created by DELL on 2017/7/29. * 权限处理类 */public class PermissionHelper { /** * 需要的参数: * 1:申请全的的Activity 或 fragment * 2:需要申请的权限 * 3:申请权限的请求码 */ private Object mObject; private String[] permissions; private int requestCode; private PermissionHelper(Object mObject){ this.mObject = mObject; } //第一种使用方式,直接传入参数 public static PermissionHelper requestPermission(Activity activity,String[] permissions,int requestCode){ return PermissionHelper.with(activity).requestCode(requestCode).requestPermission(permissions); } public static PermissionHelper requestPermission(Fragment fragment,String[] permissions,int requestCode){ return PermissionHelper.with(fragment).requestCode(requestCode).requestPermission(permissions); } //第二种方式:链式调用 public static PermissionHelper with(Activity activity){ return new PermissionHelper(activity); } public static PermissionHelper with(Fragment fragment){ return new PermissionHelper(fragment); } public PermissionHelper requestCode(int requestCode){ this.requestCode = requestCode; return this; } public PermissionHelper requestPermission(String... permissions){ this.permissions = permissions; return this; } //发起操作 public void request(){ /** * 1:判断当前手机系统是否大于或等于6.0 */ if(!PermissionUtils.isMoreThanM()){ /** * 当前系统小于6.0,则直接执行需要执行的方法,如拨号 * 由于需要执行的方法是不确定的 但Activity或fragment是已知的, * 所以这里使用注解 + 反射 的方式来获取到需要执行的方法并执行操作 */ PermissionUtils.executeSuccesseMethod(mObject,requestCode); }else{ /** * 当前系统大于 或等于6.0 * 1:判断这些权限中,是否有被被拒绝的权限 * 2:若有,则向用户申请权限 * 2.1:若申请成功 则执行成功的方法 * 2.2:若申请失败 则执行一些提示操作 * 3:若无,则直接执行成功的方法 */ ArrayList<String> deniedPermissions = getDeniedPermissions(mObject,permissions); if (deniedPermissions.size() > 0){ //有被用户拒绝的权限 需要向用户提交申请 ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject), deniedPermissions.toArray(new String[deniedPermissions.size()]),requestCode); }else{ //无被拒绝的权限 PermissionUtils.executeSuccesseMethod(mObject,requestCode); } } } public static void requestPermissionsResult(int requestCode, String[] permissions,Object object) { //再去获取以下 看看是否还有被用户拒绝的权限 ArrayList<String> deniedPermission = PermissionUtils.getDeniedPermissions(object,permissions); if(deniedPermission.size() == 0){ //用户已授权所有权限 PermissionUtils.executeSuccesseMethod(object,requestCode); }else{ /** * 还是有部分权限被用户拒绝了 * 执行一个类似提示或捕获异常等的方法 * 视情况而定 * * 这里弹出一个Toast * 套路一样 还是使用 注解 + 反射的方法 */ PermissionUtils.executeFailedMethod(object,requestCode); } }}
2.PermissionUtils: PermissionUtils的辅助类
package com.justh.dell.util; import android.app.Activity; import android.app.Fragment; import android.content.pm.PackageManager; import android.os.Build; import android.support.v4.content.ContextCompat; import android.util.Log; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; /** * Created by DELL on 2017/7/29. */ public class PermissionUtils { private static final String TAG = PermissionUtils.class.getSimpleName(); /** * * @return true or false * 如果大于或等于 返回true * 否则 返回 false */ public static boolean isMoreThanM(){ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; } /** * 执行方法 * @param object * @param requestCode */ public static void executeSuccesseMethod(Object object, int requestCode) { Class clz = object.getClass(); //通过反射获取到这个类的全部方法 Method[] methods = clz.getDeclaredMethods(); //遍历所有方法,寻找被我们加了注解的方法 for (Method method : methods){ Log.i(TAG,method+""); PermissionSucceed correctMethod = method.getAnnotation(PermissionSucceed.class); //从注解中获取到requestCode 比较是否与参数中的request一致,若一致,则可确定就是该方法 if(correctMethod != null){ if(correctMethod.requestCode() == requestCode){ //执行该方法 executeMethod(object,method); } } } } //执行方法 public static void executeMethod(Object object,Method method){ try { /** * 代表允许执行私有方法 * 若不加这句代码 * 在执行私有方法时,是会出问题滴 */ method.setAccessible(true); method.invoke(object,new Object[]{}); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } public static ArrayList<String> getDeniedPermissions(Object object, String[] permissions) { //遍历检测所有权限 将未授权的权限添加到集合中去 并返回 ArrayList<String> deniedPermissions = new ArrayList<>(); for (String permission : permissions){ if(ContextCompat.checkSelfPermission(getActivity(object),permission) != PackageManager.PERMISSION_GRANTED){ //即为被拒绝的权限 将其添加到集合中 后面统一处理 deniedPermissions.add(permission); } } return deniedPermissions; } /** * * @param object activity or fragment * @return Activity */ public static Activity getActivity(Object object){ if(object instanceof Activity){ return (Activity) object; }else if(object instanceof Fragment){ return ((Fragment) object).getActivity(); } return null; } public static void executeFailedMethod(Object object, int requestCode) { Class clz = object.getClass(); Method[] methods = clz.getDeclaredMethods(); for (Method method : methods){ PermissionFailed permissionFailed = method.getAnnotation(PermissionFailed.class); if(permissionFailed != null){ if(permissionFailed.requestCode() == requestCode){ executeMethod(object,method); } } } }}
3.PermissionSucceed :成功时的注解(相当于TAG的作用)在含有全部权限授权的情况下使用,作用在执行成功的方法的头部
package com.justh.dell.util;
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by DELL on 2017/7/29. * 执行正确的操作 */@Target(ElementType.METHOD)//代表其作用于方法中 @Retention(RetentionPolicy.RUNTIME) //表示在运行时起作用public @interface PermissionSucceed { public int requestCode();}
4.PermissionFailed:失败时的注解 在程序含有未被用户授权的危险权限时使用,作用在执行失败的方法的头部
package com.justh.dell.util;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by DELL on 2017/7/29. * 执行某些提示 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface PermissionFailed { public int requestCode();}
5:在Activity中调用:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView(){ call = (TextView) findViewById(R.id.call); call.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //检查权限 checkPermission(); } }); } private void checkPermission(){ //发起请求 PermissionHelper.with(this).requestCode(REQUEST_CODE).requestPermission(Manifest.permission.CALL_PHONE).request(); } @PermissionSucceed(requestCode = REQUEST_CODE) private void call(){ Intent intent = new Intent(Intent.ACTION_CALL); Uri data = Uri.parse("tel:" + mPhone); intent.setData(data); startActivity(intent); } @PermissionFailed(requestCode = REQUEST_CODE) private void showToast(){ Toast.makeText(this,"您拒绝了拨打电话的权限!",Toast.LENGTH_SHORT).show(); } /** * 该方法即为申请权限的回调方法 无论申请成功或者失败 都会回调这个函数 * @param requestCode 上文中提到的请求码 * @param permissions 申请的权限 * @param grantResults 申请的结果 */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); PermissionHelper.requestPermissionsResult(requestCode, permissions, this); }
到此 就真的结束了 !咵咵咵写了这么多,感觉都不知道到写了啥,希望大家能看懂吧!
如若碰到什么问题或疑问的,可以通过评论进行交流,谢谢!
- Android 6.0 动态申请权限
- android 6.0权限动态申请
- Android 6.0 动态权限申请
- Android 6.0权限动态申请
- Android 6.0 动态权限申请
- android 6.0 动态权限申请
- Android 6.0 动态权限申请
- Android 6.0动态权限申请
- Android 6.0 动态权限申请
- Android 6.0 动态申请权限
- Android 6.0权限动态申请
- Android 6.0 动态申请权限
- Android 6.0动态权限申请
- Android 6.0动态权限申请
- android 6.0动态申请权限
- Android 6.0 动态权限申请
- Android 6.0动态申请权限
- Android 6.0 动态权限申请
- Spark 键值对RDD操作
- C语言——实例009 输出国际象棋棋盘。
- 函数(2)
- git 总结
- 分布式存储-fastdfs+glusterfs- 学习笔记
- Android 6.0动态权限申请
- hdu 4990 Reading comprehension(矩阵乘法)
- 美国国家安全局如何分析通话数据
- Tomcat启动报错:org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalin
- unity3d实现一个魔方旋转展示
- 2016校招真题编程练习——微信红包(腾讯)
- 两道面试题——进制各位数之和
- 【动态规划】最长上升子序列及其相关思想
- 1018. Public Bike Management (30)