android权限大全(Android权限限制怎么解除)

张工 2022-05-28 19:05:35 阅读:86
  

如何优雅地申请Android运行时权限

  转载本文需注明出处:微信公众号EAWorld,违者必究。

前言:

  Android是一个特权分离的操作系统,其中每个应用程序都有自己唯一的系统标识。默认情况下,任何应用程序都无权执行任何会对其他应用程序、操作系统或用户产生不利影响的操作。这包括读取或写入用户的私人数据(例如,联系人或电子邮件),读取或写入其他应用程序的文件,执行网络访问,保持设备清醒等。

  ――引自谷歌Android开发文档

目录:

  1.Android权限的演变

  2.运行时权限申请

  3.Android权限开源库

  4.如何优雅地申请许可?

1.Android权限的演化

  Android6.0之前

  在Android6.0之前,应用权限只需要在代码中的AndroidManifest.xml中声明就可以获得,不需要询问用户的权限。有些app申请了很多权限,甚至有些工具类应用居然申请了短信、录音、读取手机文件等敏感权限。当然,那也是流氓软件最盛行的时代,无数应用在后台窃取用户的敏感数据。

  Android6.0之后

  Android6.0以后,应用权限被Google分为两类,正常权限和危险权限。正常权限可以通过在AndroidManifest.xml中声明来获得,而危险权限需要在使用前向用户申请,只有在用户同意的情况下才能使用。如果在没有应用到用户的情况下执行操作,应用会直接报错闪回。

  危险和权限组:

如何优雅地申请Android运行时权限

2.运行时权限的申请

  使用Android权限的原则

  根据谷歌官方文档的说明,建议遵守以下四条原则:

  仅使用正常操作所需的权限。请注意,库所需的权限是开放和透明的,因此系统可以显式地访问它们。

  简单来说,除非你真的需要,否则不要请求允许。

  如何申请权限

  判断是否已获取权限

  int has permission=context compat . checkselpermission(get application(),manifest . permission . write _ EXTERNAL _ STORAGE);

  if(has permission==package manager。PERMISSION_GRANTED) {

  //已经获得权限

  }否则{

  //未获得权限

  }

  申请权限

  @ override public void onrequestpermissions result(Int request code,String[] permissions,Int[]grant results){ if(request code==requestpermissioncode){ if(grant results . length 0 grant results[0]==package manager . permission _ granted){//用户同意了权限申请}else{ //用户拒绝了权限申请,建议向用户说明权限的用途}}

  在Activity中注册回调

  @覆盖

  public void onrequestpermissions result(int request code,String[] permissions,

int[] grantResults) { if (requestCode == RequestPermissionCode){ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ //用户同意了权限申请 }else{ //用户拒绝了权限申请,建议向用户解释权限用途 } }}

3.Android权限开源库

  

  通过上述示例看到申请权限代码比较繁琐,需要判断权限、申请权限、在Activity中注册权限申请结果的回调。社区中有很多运行时权限的开源库,下面github上star比较多的这四个。

  

如何优雅地申请Android运行时权限

  

  PermissionsDispatcher

  

  本库基于注解来实现,且支持Java/Kotlin。因为是在你实现的方法上加注解来请求权限,所以代码相对要简洁一些,我们基本上要使用到以下几个注解。

  

如何优雅地申请Android运行时权限

  

  同样,在写完申请完权限后执行的方法后,同样要在Activity的onRequestPermissionsResult中注册回调。

  

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {              super.onRequestPermissionsResult(requestCode, permissions, grantResults)              // NOTE: delegate the permission handling to generated function              onRequestPermissionsResult(requestCode, grantResults)        }

  

  RxPermissions

  

  同样也是一个优秀的开源库,这个库提供了如同RxJava风格的权限申请方法,代码简洁,只需要AppCompatActivity即可初始化,并可以在任意位置调用。但需要引入RxJava库。

  

final RxPermissions rxPermissions = new RxPermissions(this);// Must be done during an initialization phase like onCreaterxPermissions      .request(Manifest.permission.CAMERA)      .subscribe(granted -> {          if (granted) { // Always true pre-M               // I can control the camera now          } else {             // Oups permission denied        }});

  

  easypermissions

  

  googlesamples中提供的方法,使用EasyPermissions.requestPermissions申请权限,同时也需要在Activity的onRequestPermissionsResult中注册回调。

  

  AndPermission

  

  仅支持androidx,同样需要Activity来初始化,代码也比较简洁。

  

AndPermission.with(this)   .runtime()    .permission(Permission.Group.STORAGE)    .onGranted(permissions -> {      // Storage permission are allowed.  })    .onDenied(permissions -> {      // Storage permission are not allowed.  })    .start();

  

  总的来说,每个库都有各自的优缺点,大家可以根据具体需求选用最适合自己项目的库。

  

4.如何优雅地申请权限

  

  吐槽:开源库代码繁琐,文档有限,问题解答不及时。。。

  

  各自项目有着不同的需求,这些丰富的开源库可能仍然无法满足我们的要求,不仅是权限申请,其他功能也是一样。接下来将手把手带大家造一个简化权限申请代码的轮子。

  

  整体思路

  

  绝大多数开源库在申请权限的时候要在Activity中onRequestPermissionsResult注册回调,这一点我是很反感的,代码侵入性太大了。

  

  假如我封装了一个获取定位的接口,这是一个独立的方法,一般来说会写在LocationUtils.java中,而且任何人任何类类都可能调用我的方法,这就导致LocationUtils是没有Activity去接收onRequestPermissionsResult回调的数据。相信这也是大多数开发者遇到的主要问题之一。

  

  所以,在应用中,我可以加载一个Fragment(和RxPermissions思路类似),在fragment中申请权限,onRequestPermissionsResult回调也放在这个fragment中。这样我在任何位置,只要有Activity存在,都可以加载这个fragment去请求权限,请求完成后再移除这个fragment。

  

public static void requestPermission(final Activity context, final String[] permissions, PermissionCallback permissionCallback) {          permissionFragment.setOnAttachCallback(new FragmentAttachCallback() {                         @Override                          public void onAttach() {                                    permissionFragment.requestPermission(permissions);                          }       });       permissionFragment.setOnPermissionCallback(permissionCallback);       FragmentTransaction fragmentTransaction = context.getFragmentManager().beginTransaction();       //让我在评论区看到你们的777      fragmentTransaction.add(permissionFragment, "permissionFragment@777").commit();

  

  当然我们也可以借助getTopActivity方法,让权限库自己去获取栈顶的Activity,这样只需要传入需要申请的权限和权限结果的回调即可。

  

PermissionAnywhere.requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}                          , permissionCallback);

  

  其中PermissionCallback中会回调用户点击同意的权限,用户点击拒绝的权限,用户点击不再提示且拒绝的权限三种。

  

public interface PermissionCallback {      void onComplete(List<String> grantedPermissions, List<String> deniedPermissions, List<String> alwaysDeniedPermissions);}

  

  使用方法

  

  1、在根目录build.gradle中增加

allprojects {      repositories {           ...            maven { url 'https://jitpack.io' }      }}

  

  2、增加依赖

dependencies {      implementation 'com.github.mingyuers:PermissionAnywhere:latest.release'}

  

  代码下载地址

  

  以上完整代码已开源到github:

  https://github.com/mingyuers/PermissionAnywhere

  欢迎大家研究学习,欢迎star,欢迎pr。

  

  延伸

  

  其实也可以使用1px的Activity进行权限申请,这样能否实现在Application中申请权限?会不会引申出别的问题呢?欢迎大家在留言区讨论。

  

如何优雅地申请Android运行时权限

  关于作者:明月,现任普元移动团队资深开发工程师,长期致力于IT技术研究,产品设计和开发等工作,擅长Java、NodeJs、ReactNative等领域技术。先后参加深圳登、太保等移动项目的实施,参与Mobile 8.0移动平台的设计开发工作。

  关于EAWorld:微服务,DevOps,数据治理,移动架构原创技术分享。

二维码