目录

   一、引言
   二、效果
   三、Normal Permission和Dangerous Permission
   四、实现支持运行时权限
   五、permissionsdispatcher框架的使用

一、引言

  在Android 6.0以前(targetSdkVersion 23)以前,我们安装APP时会列出所有该APP在Manifest中列出的访问权限,而且只会出现一次,一旦我们同意安装此APP并同意所有权限,APP就可以在用户不知情的情况下访问手机中的数据,包括(通讯录、定位)等隐私,在6.0以后,APP在运行时会一个一个询问用户授予权限。


二、效果

正常允许权限:

拒绝允许权限的处理


三、Normal Permission和Dangerous Permission

Google给出的关于权限分类的官方文档,
https://developer.android.google.cn/guide/topics/security/permissions.html#normal-dangerous

Dangero Permission以分组形式给出

在Android6.0(API 23) 到8.0(API 26)之间,同一组的任何权限被授权了,其他权限也自动授权,此外对于申请时弹出的提示框上面的文本说明也是对整个权限组的说明,而不是单个权限的说明。但是Android 8.0(APi 26)以后对于危险权限需要一个一个的申请。


四、实现支持运行时权限

1、首先是我们拨打电话的点击事件:

 dialBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {call();}});

2、这时进行权限的检查,是否拥有拨打电话的权限,如果有则进行拨号,如果没有进行权限的申请:

 private void call() {//检查APP是否有权限if(ActivityCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){//如果没有ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CALL_PHONE},PERMISSION_REQURST_CALL_PHONE);}else{callPhone();}}/*** 拨打电话*/private void callPhone() {Intent intent = new Intent(Intent.ACTION_CALL);Uri data = Uri.parse("tel:"+ 10086);intent.setData(data);startActivity(intent);}

3、权限申请回调的处理:

 @Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if(requestCode == PERMISSION_REQURST_CALL_PHONE){if(grantResults[0] != 0  && grantResults[0] == PackageManager.PERMISSION_GRANTED){//允许申请的权限callPhone();}else{//申请权限被拒绝Toast.makeText(this,"申请权限被拒绝",Toast.SHORTTIME).show();}return;}super.onRequestPermissionsResult(requestCode, permissions, grantResults);}

4、处理“不再询问”选项
  在申请权限时,如果我们点击“拒绝”,则下一次还会继续弹出权限申请框,只不过这一次会多出来一项“不再询问”,如果我们勾选了这个选项,则下一次不会再弹出此权限申请框,用户需要去设置—》应用权限列表中手动打开权限。

用户对于已经勾选“不再询问”的权限,每次调用该权限API时都会失效,用户无法使用该功能,这显然不会带来好的用户体验,这个时候我们需要使用shouldShowRequestPermissionRationale()方法向用户解释权限使用情况,并设置进入应用的设置权限所在:

 @Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if(requestCode == PERMISSION_REQURST_CALL_PHONE){if(grantResults[0] != 0  && grantResults[0] == PackageManager.PERMISSION_GRANTED){callPhone();}else{if(!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.CALL_PHONE)){final AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle("提示").setMessage("该功能需要访问电话的权限,否则无法使用").setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {dialogInterface.dismiss();}}).setPositiveButton("前去设置", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//跳转到当前APP的设置页面Intent intent = new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.addCategory(Intent.CATEGORY_DEFAULT);intent.setData(Uri.parse("package:" + getPackageName()));intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);startActivity(intent);}}).create();dialog.show();}}return;}super.onRequestPermissionsResult(requestCode, permissions, grantResults);}

五、permissionsdispatcher框架的使用

1、依赖
在Project的build.gradle 中添加如下代码:

dependencies {...classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'}

在app的build.gradle中添加依赖:

dependencies {implementation 'com.github.hotchemi:permissionsdispatcher:2.1.3'annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.1.3'
}

permissionsdispatcher以注释的方式进行权限的处理,其中几个重要的注释:

注释名称 注释解释
RuntimePermissions 必要的注释,用来注册一个Activity或者一个Fragment,使他们可以处理权限
NeedsPermission 必要的注释,在需要获取权限的地方进行注释,用来获取权限
OnShowRationale 提示用户为何需要开启此权限,在用户选择拒绝后,再次需要访问该权限时调用
OnPermissionDenied 用户选择拒绝时的提示
OnNeverAskAgain 用户选择不再询问后的提示

代码如下:


import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.OnShowRationale;
import permissions.dispatcher.PermissionRequest;
import permissions.dispatcher.RuntimePermissions;@RuntimePermissions
public class SecondActivity extends AppCompatActivity {private Button dialBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);initView();}private void initView() {dialBtn = (Button) findViewById(R.id.dial_btn);dialBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {}});}@NeedsPermission(Manifest.permission.CALL_PHONE)//在需要获取权限的地方注释void call(){Intent intent = new Intent(Intent.ACTION_CALL);Uri data = Uri.parse("tel:" + 10086);intent.setData(data);startActivity(intent);}@OnShowRationale(Manifest.permission.CALL_PHONE)//提示用户为何要开启权限void showWhy(final PermissionRequest request){new AlertDialog.Builder(SecondActivity.this).setMessage("提示用户为何要开启权限").setPositiveButton("知道了", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {request.proceed(); //再次执行权限请求}}).show();}@OnPermissionDenied(Manifest.permission.CALL_PHONE)void showDenied(){Toast.makeText(SecondActivity.this,"用户选择拒绝时的提示",Toast.LENGTH_SHORT).show();}@OnNeverAskAgain(Manifest.permission.CALL_PHONE)void showNotAsk(){new AlertDialog.Builder(SecondActivity.this).setMessage("该功能需要访问电话的权限,不开启将无法使用该功能").setPositiveButton("前去设置", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//跳转到当前APP的设置页面Intent intent = new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.addCategory(Intent.CATEGORY_DEFAULT);intent.setData(Uri.parse("package:" + getPackageName()));intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);startActivity(intent);}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {dialogInterface.dismiss();}}).show();}}

这个时候我们编译程序,会生成一个辅助类SecondActivityPermissionsDispatcher,下面的事情由它进行解决,完整代码:

@RuntimePermissions
public class SecondActivity extends AppCompatActivity {private Button dialBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);initView();}private void initView() {dialBtn = (Button) findViewById(R.id.dial_btn);dialBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//*****************重点*****************SecondActivityPermissionsDispatcher.callWithCheck(SecondActivity.this);}});}@NeedsPermission(Manifest.permission.CALL_PHONE)//在需要获取权限的地方注释void call(){Intent intent = new Intent(Intent.ACTION_CALL);Uri data = Uri.parse("tel:" + 10086);intent.setData(data);startActivity(intent);}@OnShowRationale(Manifest.permission.CALL_PHONE)//提示用户为何要开启权限void showWhy(final PermissionRequest request){new AlertDialog.Builder(SecondActivity.this).setMessage("提示用户为何要开启权限").setPositiveButton("知道了", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {request.proceed(); //再次执行权限请求}}).show();}@OnPermissionDenied(Manifest.permission.CALL_PHONE)void showDenied(){Toast.makeText(SecondActivity.this,"用户选择拒绝时的提示",Toast.LENGTH_SHORT).show();}@OnNeverAskAgain(Manifest.permission.CALL_PHONE)void showNotAsk(){new AlertDialog.Builder(SecondActivity.this).setMessage("该功能需要访问电话的权限,不开启将无法使用该功能").setPositiveButton("前去设置", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {//跳转到当前APP的设置页面Intent intent = new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);intent.addCategory(Intent.CATEGORY_DEFAULT);intent.setData(Uri.parse("package:" + getPackageName()));intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);startActivity(intent);}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {dialogInterface.dismiss();}}).show();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);//*****************重点*****************SecondActivityPermissionsDispatcher.onRequestPermissionsResult(SecondActivity.this,requestCode,grantResults);}
}

OK ,这是权限里面的内容了,希望能帮到你

Permission(使用与框架使用)相关推荐

  1. SyncAdapter同步机制

    官方文档:https://developer.android.com/training/sync-adapters/index.html 1.简介 在Android设备和web服务器之间同步数据会使你 ...

  2. Android文档阅读之Txt文档阅读的方案实现

    Android文档阅读之Txt文档阅读的方案实现 上两节说到了Office文档的阅读实现方案,通过NoHTTP将文档下载到本地,然后策略阅读,如果还没阅读到Office该篇的小伙伴们,可以先移步到上两 ...

  3. Android MVVM框架搭建(七)Permission、AlertDialog、拍照和相册选取

    Android MVVM框架搭建(七)Permission.AlertDialog.拍照和相册选取 前言 正文 一.数据库升级 二.数据操作 二.自定义Dialog ① DialogViewHelpe ...

  4. java安全框架下载文件_java安全框架之Permission学习笔记

    一.permission和security policy java.security.Permission代表一个访问系统资源的系统资源的权限,perm = new java.io.FilePermi ...

  5. iOS 关于pods-frameworks.sh:permission denied报错的解决

    最近公司新开项目,搭建完框架后小伙伴拉取代码后build一直报错:pods-frameworks.sh:permission denied 查了很多博文后找到了如下解决方案,在此记录. 打开终端输入如 ...

  6. 智销功能_Shiro权限框架

    Shiro是什么? Spring security 重量级安全框架 Apache shiro 轻量级安全框架 Shiro是一个强大且易用的Java权限框架 四大基石 身份验证,授权,密码学,会话管理 ...

  7. ssh框架实现数据库_自顶向下介绍SSH及其如何实现安全的数据共享

    ssh框架实现数据库 by Sam Ollason 通过萨姆·奥拉森(Sam Ollason) This article will take a high-level and top-down app ...

  8. 还在用Spring Security?推荐你一款使用简单、功能强大的权限认证框架

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/qq_40058629/article/ details/116692302 我们先看一下官网介绍 ...

  9. Java 程序员如何使用 Shiro 框架

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:冷豪 来自:www.cnblogs.com/learnhow ...

最新文章

  1. 零售行业常用分析报表:(一)
  2. JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化
  3. UVA 146 ID Codes
  4. jQuery Tab
  5. HDU 1019 Least Common Multiple
  6. mybatis oracle 大写,解决mybatis用Map返回的字段全变大写的问题
  7. 从无到有整合SpringMVC-MyBatis项目(2):搭建SpringMVC项目
  8. C++继承:公有,私有,保护
  9. OpenCV-图像处理(27、模板匹配(Template Match))
  10. 全面解析免费及收费SSH工具的基本特性和总结
  11. JAVA 中字符串的长度
  12. 一个可以把单张静态照片转化成 3D 图片的AI 工具
  13. 入手评测 联想小新PRO14,华硕灵耀14s和联想YOGA14s选哪个
  14. 好用的在线奖状生成工具推荐!
  15. 网页版微信和微信公共号扫码登陆原理分析
  16. Python编程快速上手让繁琐工作自动化中文高清完整版PDF带书签
  17. 隐患排查和安全生产预警系统解决方案
  18. Python_Task06:函数与Lambda表达式
  19. Greenplum 的备份与恢复
  20. ab间奇数的和c语言,小学五年级奥数奇数与偶数(AB)试题

热门文章

  1. 警惕界面上的异步回调
  2. java swing(GUI图形化界面)基础教程1
  3. 周易六十四卦——大壮卦
  4. 极客日报第 12 期:微博就违规收集使用个人信息致歉;雷军回应“小米手机都是中低端”
  5. Ubuntu sudo apt-get update提示 Failed to fetch,解决办法
  6. 【Python摸鱼】Python自动工作汇报脚本,实现每天轻松上班,快乐摸鱼 ~
  7. 东邪西毒终极版经典台词
  8. 沉下心来 ,这次,认真一点!
  9. Haproxy 负载解决方案
  10. java的布局管理器_Java中提供了几种布局管理器