android 6.0以上动态一次申请多个权限-最美解决方案

目录

  • 背景
  • 危险权限
  • 申请权限思路
  • 申请权限流程
  • 干货
  • 后续

一.背景

android23 API新增危险权限校验,需要手动获取:

二.危险权限:

日历数据
android.permission-group.CALENDAR   
android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR
相机
android.permission-group.CAMERA 
android.permission.CAMERA
联系人
android.permission-group.CONTACTS   
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS
位置
android.permission-group.LOCATION   
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
麦克风
android.permission-group.MICROPHONE 
android.permission.RECORD_AUDIO
电话
android.permission-group.PHONE  
android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
com.android.voicemail.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS
传感器
android.permission-group.SENSORS    
android.permission.BODY_SENSORS
短信
android.permission-group.SMS    
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_CELL_BROADCASTS
存储
android.permission-group.STORAGE    
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE

三.申请权限思路

Android6.0 运行时权限,相关的方法主要有四个:
1、检查是否授予权限
ContextCompat.checkSelfPermission(mContext, permissions[i])
返回的结果为PackageManager.PERMISSION_GRANTED(0)表示授予权限

2、请求权限
ActivityCompat.requestPermissions(WelcomeActivity.this, permissions, 1);
注:permissions为数组,单个的权限,传new String[]{permission}参数, 1为requestCode,在权限回调中需要使用。

3、请求权限后的回调
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

4、判断用户拒绝权限是是否勾选don't ask again选项,若勾选需要客户手动打开权限
ActivityCompat.shouldShowRequestPermissionRationale(WelcomeActivity.this, permissions[i])

注:ActivityCompat.shouldShowRequestPermissionRationale(activity,permission) 这个方法是在用户拒绝权限后返回true。也就是说:用户第一次点击一个需要权限的地方,该方法返回false(因为用户没拒绝~),当用户拒绝掉该权限,下次点击此权限处,该方法会返回true。为true的时候,显示对话框对该权限说明,并让用户选择是否再次申请权限。当用户拒绝权限并勾选don't ask again选项后,会一直返回false,并且 ActivityCompat.requestPermissions 不会弹出对话框,系统直接deny,并执行 onRequestPermissionsResult 方法

5、总结
①、检查需要申请的权限状态,将未授权的单独保存到集合中;
②、集合为空,进入首页(已全都授予权限),不为空,请求权限;
③、当用户拒绝时,判断是否勾选don't ask again,未勾选,重新申请权限,已勾选,跳过欢迎界面,进入主界面。

四.申请权限流程

A、在实际项目中,为了开发的方便,在欢迎界面,将常用的权限申请一次性申请,一般申请写存储卡、定位等权限。
申请权限分为两类: ① 直接弹出权限框,允许或禁止操作 ② 到手机具体某个页面设置。
B、在某个具体操作的时候(如:悬浮窗权限)再单独进行权限判断。
C、具体操作权限申请流程:
①、请求权限;
②、在请求回调中,当用户拒绝时,需判断是否勾选don't ask again,
未勾选,重新申请权限,
已勾选,跳转到设置界面。

五、干货

用户是否禁止权限
private  boolean mShowRequestPermission = true;

申请权限  -- 进入登录页面时申请权限
 private void init_permission() {
      if (getSdkVersionSix()) {
          String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE, Manifest.permission.RECORD_AUDIO};
          List<String> mPermissionList = new ArrayList<>();
          for (int i = 0; i < permissions.length; i++) {
              if (ContextCompat.checkSelfPermission(LogInAct.this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                  mPermissionList.add(permissions[i]);
              }
          }

          if (mPermissionList.isEmpty()) {// 全部允许
              mShowRequestPermission = true;
          } else {//存在未允许的权限
              String[] permissionsArr = mPermissionList.toArray(new String[mPermissionList.size()]);
              ActivityCompat.requestPermissions(LogInAct.this, permissionsArr, 101);
          }
      }
  }

权限提示框 ,如果点击禁止且不勾选禁止访问,则无线循环弹出申请框,哈哈,就是这么任性。
如果全部允许则正常操作。如果全部禁止且禁止访问,点击登录按钮时再校验一遍,

 @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
      super.onRequestPermissionsResult(requestCode, permissions, grantResults);
      switch (requestCode) {
          case 101:
              for (int i = 0; i < grantResults.length; i++) {
                  if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                      //判断是否勾选禁止后不再询问
                      boolean showRequestPermission = ActivityCompat.shouldShowRequestPermissionRationale(LogInAct.this, permissions[i]);
                      if (showRequestPermission) {
                          init_permission();
                          return;
                      } else { // false 被禁止了,不在访问
                          mShowRequestPermission = false;//已经禁止了
                      }
                  }
              }
              break;
      }
  }

  点击登录按钮时 ,获取申请权限的结果 并且这里动态申请了“悬浮窗”的权限
 1. 如何小于6.0 直接登陆
 2. 申请悬浮窗权限,如果没有,直接跳转到具体页面进行设置,完成后在onActivityResult 中判断是否允许该权限
   如果允许再次动态申请一次权限,上面如果点击了全部禁止且勾选了禁止访问请调用 getRequestPermission()方法,          
   自动跳转到应用程序列表中让用户手动设置权限

   if (getSdkVersionSix()) {
              if (Settings.canDrawOverlays(LogInAct.this)) {
                  if (getRequestPermission().equals("1")) { // 如果等于1则登录
                      init_IntentLogIn(getAccount(), getPwd());
                  }
              } else {
                  Toast.makeText(this, R.string.login_canDrawOverlays,   Toast.LENGTH_SHORT).show();
                  Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                  startActivityForResult(intent, 2);
              }
          } else {
              init_IntentLogIn(getAccount(), getPwd()); // 6.0以下直接登录
   }

  判断SDK是否在6.0以上
  public boolean getSdkVersionSix() {
      return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
  }
  
  处理申请的悬浮窗和其他权限
  @RequiresApi(api = Build.VERSION_CODES.M)
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      if (requestCode == 2) {
          if (Settings.canDrawOverlays(LogInAct.this)) {
              init_permission();
          } else {
              Toast.makeText(this, R.string.login_canDrawOverlays, Toast.LENGTH_SHORT).show();
          }
      } else if (requestCode == 3) {
          init_permission();
      }
  }

  申请权限后的操作
   public String getRequestPermission() {
      if (mShowRequestPermission) {
          return "1";
      } else {// 被禁止后提示用户必须到设置中授权,跳转到应用程序列表页面
          Toast.makeText(this, R.string.login_permission, Toast.LENGTH_SHORT).show();
          Intent intent = new Intent(Settings.ACTION_APPLICATION_SETTINGS);
          startActivityForResult(intent, 3);
          return "-1";
      }
  }

六、后续

工具类已出 ,代码传送门

七、远程依赖

1.gradle


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

dependencies {
            implementation 'com.github.stf-android:Permissions:-SNAPSHOT'
    }

2.maven

    <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
    </repositories>

     <dependency>
        <groupId>com.github.stf-android</groupId>
        <artifactId>Permissions</artifactId>
        <version>-SNAPSHOT</version>
    </dependency>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容