Android动态权限总结

栏目: IOS · Android · 发布时间: 5年前

内容简介:从Android6.0开始,Android系统提供动态申请权限的机制, APP在使用危险权限时,需要用户的授权才可进一步操作。Android系统中权限申请的方式有两种,如下图所示:Android6.0以前的系统(API < 23)采用的这种方式,只要用户在AndroidManifest.xml中注册了权限,安装APP后默认就获取了这些权限。这种授权方式安全性极低,如果用户安装后没有关闭相应的权限,用户的私密数据很容易被哪些垃圾APP窃取。为了解决这种问题,国内的各大手机厂商为Android5.0以下的系统

从Android6.0开始,Android系统提供动态申请权限的机制, APP在使用危险权限时,需要用户的授权才可进一步操作。

权限申请方式

Android系统中权限申请的方式有两种,如下图所示:

Android动态权限总结

静态申请

Android6.0以前的系统(API < 23)采用的这种方式,只要用户在AndroidManifest.xml中注册了权限,安装APP后默认就获取了这些权限。这种授权方式安全性极低,如果用户安装后没有关闭相应的权限,用户的私密数据很容易被哪些垃圾APP窃取。为了解决这种问题,国内的各大手机厂商为Android5.0以下的系统,针对某些权限做了一定的限制,即便在Android5.0以下,也需要用户进行手动授权才可使用,这在某种程度上提高了安全性,但也因没有统一的标准,从而出现了各种兼容问题。

动态申请

随着系统的升级,Google也意识到静态申请权限的弊端,所以在Android6.0中,对权限进行了重新梳理,将权限分为普通权限和危险权限:

  • 正常权限:不会给用户隐私带来危险的权限,只要开发者在AndroidManifest.xml中注册了,系统将自动授权;
  • 危险权限:可以访问用户隐私数据的权限,必须获取用户的同意才可获得授权;

危险权限汇总

Android动态权限总结

在Android开发中我们应该尽可能使用隔离式申请权限,用户没有授权时屏蔽相应功能即可。现在很多内容性APP,用户进去什么都没看到,就需要各种权限,没有权限还不能使用,这可能会引起用户的反感,当然,也是对用户安全意识的一种冲击,时间久了,用户可能会觉得使用APP就应该授权,从而给一些恶意APP作恶的余地。

动态申请权限的过程

Android动态权限总结

核心API介绍

检查权限是否已获取:

// ContextCompat.java 
public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) 
 
// PermissionChecker.java 
public static int checkSelfPermission(@NonNull Context context, 
            @NonNull String permission) 

这两个方法都是检查权限是否获取的方法,但ContextCompat.checkSelfPermission在某些系统上(如基于Android8.0的MIUI10检查短信权限时)有bug, 不能准确判断权限是否已获取,此时可结合PermissionChecker.checkSelfPermission进行判断, 所以判断权限是否已获取可采用以下实现:

public static boolean hasPermission(@NonNull Context context, @NonNull String permission) { 
    if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED 
            || PermissionChecker.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { 
        return false; 
    } 
 
    return true; 
} 

申请权限

当未获取权限时,需要向系统请求,请求时使用requestPermissions方法:

// ActivityCompat.java 
// 在Activity中申请权限 
public static void requestPermissions(final @NonNull Activity activity, 
            final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) 
         
 
// Fragment.java 
// 在Fragment中申请权限 
public final void requestPermissions(@NonNull String[] permissions, int requestCode) 

在Fragment使用ActivityCompat.requestPermissions申请权限时,如果用户拒绝了(且勾线了不再提示)请求,Fragment中的onRequestPermissionsResult不会被回调,也就不能引导用户开启权限。所以在Fragment中应该使用Fragment的成员方法requestPermissions来请求权限。

检查APP是否应该向用于展示申请权限的解释

// ActivtyCompat.java 
// 检查APP是否应该向用于展示申请权限的解释 
public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission); 

此方法的返回值解释如下:

  • 当APP从未申请过指定的权限或申请了指定权限,但被用户拒绝,且勾选了【不再提示】,返回false;
  • APP申请指定权限时被用户拒绝,但未勾选【不再提示】,返回true

所以在使用此方法时,我们要先判断APP是否已申请过权限,否则难以判断返回false的两种情况。

申请权限的结果回调

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 

这是Activity和Fragment中申请权限的结果回调方法,其中permissions表示申请的权限数组,grantResults表示每个权限的请求结果。取值为:

// 获得授权 
public static final int PERMISSION_GRANTED = 0; 
// 未获授权 
public static final int PERMISSION_DENIED = -1; 

通常申请权限后的处理逻辑都是在该方法中实现。

动态权限申请的实现

动态申请权限的条件:

  • targetSdkVersion >= 23;
  • Android系统版本在6.0及以上;

对于不能同时满足以上条件的情况,默认使用的静态申请权限的方式,但不同的ROM为了安全性,可能对其机制进行了修改,所以可能因ROM不同而有所差异。

了解了申请权限的核心API,接下来就介绍一下在Activity中申请权限的实现过程,下面以点击申请拍照权限为例:

private void startPhoto() { 
    if (hasPermission(this, new String[]{Manifest.permission.CAMERA})) { 
        // 执行拍照的逻辑 
    } else { 
         ActivityCompat.requestPermissions(context, rnew String[]{Manifest.permission.ACCESS_FINE_LOCATION}), 
                        PERMISSION_REQUEST_CODE); 
    } 
} 

然后在onRequestPermissionsResult中监听权限申请的结果:

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     
    if (hasPermission(permissions)) { 
        // 执行拍照的逻辑 
    } else { 
        if (ActivityCompat.shouldShowRequestPermissionRationale(context, permissions[refusedPermissionIndex])) { 
            // 向用户展示申请权限的理由 
        } else { 
            // 引用用户去开启权限 
        } 
    } 
} 

上面只是一个申请权限的基本流程,真正实现时还要考虑多权限问题,版本的兼容问题,ROM的兼容问题等。

当然,在开发中也不会这样在每个需要申请权限的Activity/Fragment中写这一段代码,即便封装成 工具 类也需要在每个Activity/Fragment引用,耦合性太高。通常可将权限申请在一个透明的Activity中实现,这样在申请权限时,直接跳转到该Activity即可。下面推荐一个动态申请权限的库供参考。

PermissionManager

PermissionManager是一个基于AOP实现的动态申请权限的开源库,目的是让申请权限的过程更简单。当然,也可当做学习Aspectj的的参考项目。具有以下优点:

  • 支持多权限申请;
  • 简单易用,一行注解实现权限申请
  • 提供了可扩展的权限说明和引导设置方式;
  • 提供了阻塞/非阻塞的申请方式;
  • 具体的介绍可参考其源码地址:PermissionManager

总结

由于Android碎片化严重,国内的各大厂商对权限这块也做了不同的处理,所以在动态申请时肯定存在失败的情况,如果在使用PermissionManager的时候发现问题,欢迎随时提issue & pull request。


以上所述就是小编给大家介绍的《Android动态权限总结》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

奔腾年代

奔腾年代

郭万盛 / 中信出版集团 / 2018-9-1 / 68.00

1994年4月20日,一条64K国际专线将中关村地区教育与科研示范网络与互联网连在了一起。中国,成为第77个全功能接入互联网的国家。 1995年,中国互联网正式开始商业化应用。浪潮开始! 这是一个波澜壮阔的年代,带给我们翻天覆地的变化。中国互联网25年发展史的全景展示、忠实梳理和记录。 在更宏观的角度审视互联网与中国的关系,人们将会发现,互联网革命给中国带来了重新崛起的时代机遇。......一起来看看 《奔腾年代》 这本书的介绍吧!

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具