Android 6.0 权限机制等新特性

1、电源管理

App Standby(应用待机)

  • 检测:当设备未充电,且在这段时间內用户没有直接或者间接的启动该应用。
  • 退出:当应用激活时,或者设备充电时,系统将应用移除此状态。

Doze

  • 检测:当设备未充电,且当设备静止或灭屏一段时间
  • 周期:平台尝试让系统处于休眠状态,周期性地进入在一个维持窗口恢复正常操作,然后进入更长的休眠状态
    (理解:如果用户不操作手机,android先进入一个休眠状态,过段时间再检测还是未操作,就进入下一级休眠状态,以此类推,知道进入最高级别的休眠状态,以达到省电)

2、App Link(非新,加强力度)

  • 全称为 应用程序链接
  • 技术点: 就是隐式启动Intent
  • android更加鼓励应用程序间的关联而不再是单一的应用同浏览器的交互

指纹识别

  • 6.0以前一直由各手机制造厂商去研发,导致指纹识别不同的手机差异巨大
  • 6.0以后将由android系统提供api,硬件厂商只需提供相应的硬件支持即可

3、应用程序权限管理

权限机制

  • 5.0以前,只需要manifest.xml中注册声明即可
  • 5.0以后,用户可以在安装的时候关闭某些权限
  • 6.0及以后,对于一些用户隐私权限总是会在第一次提示用户是否授予权限(类似iPhone)

运行时权限的优势

  • 新的权限机制更好的保护了用户的隐私
  • 给了程序向用户说明权限的作用
  • 可以防止一些恶意程序盗取用户或者手机信息,增强了android系统的安全性

运行时权限的分类

  • Normal Premission

一些不涉及隐私的权限,不需要单独去申请,只需要在manifest申请就可以

  • Dangerous Permission & Dangerous Premission Group

涉及隐私的权限,会在运行时向用户申请。并且会分单独的权限和权限组的形式。例如:读sd卡和写sd卡可以合并成操作sd卡的组形式的权限组

权限组的概念

  • 如果你申请某个危险的权限,假设你的app早已被用户授权了同一个组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权

新权限使用实例

新增API

  • ContextCompact.checkSelfPermission()

    检测app是否拥有此权限

  • ActivityCompat.requestPermissions()

    申请某个权限

  • onRequestPermissionsResult()

    申请权限的回调,处理申请权限成功失败

  • ActivityCompat.shouldShowRequestPermissionRationale

    用于给用户解释申请改权限是用于做什么的。用户拒绝我们的申请之后才会出现

使用流程

  • 在AndroidManifest中添加需要的权限(不可省)

  • 检查权限

      shell命令:
      adb shell pm list permissions -d -g
    
  • 申请授权

  • 处理申请回调

代码实战

  • 运用上述流程实现一个拨打电话的权限请求过程

    1、先在AndroidManifest.xml中注册权限

      
    

    2、在MainActivity中检查权限,如果有直接执行拨打电话。如果没有权限,请求权限

      if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
              != PackageManager.PERMISSION_GRANTED){
          // 做权限申请处理
          ActivityCompat.requestPermissions(this, 
              new String[]{Manifest.permission.CALL_PHONE}, Constants.CALL_PHONE);
      }else{
          // 已经有改权限
          doCallPhone();// 拨打电话的具体实现
      }
    

    3、处理onRequestPermissionsResult回调

      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          switch (requestCode){
              case Constants.CALL_PHONE:
                  if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                      doCallPhone();
                  }else{
                      // 请求被拒绝,提示用户
                      Snackbar.make(fabCall, "拨打电话权限被拒绝", Snackbar.LENGTH_SHORT).show();
                  }
                  break;
          }
      }
    
  • 当前我们只添加了一个权限,代码就很臃肿了,所以可以考虑封装我们请求权限的代码到BaseActivity中。

    BaseActivity.java

      public class BaseActivity extends AppCompatActivity {
      
          public boolean hasPermission(String... permissions){
              for(String per : permissions){
                  if(ContextCompat.checkSelfPermission(this, per)
                          != PackageManager.PERMISSION_GRANTED){
                      return false;
                  }
              }
              return true;
          }
      
          public void requestPermission(int code, String... permissions){
              ActivityCompat.requestPermissions(this, permissions, code);
          }
      
          @Override
          public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
              super.onRequestPermissionsResult(requestCode, permissions, grantResults);
              switch(requestCode){
                  case Constants.WRITE_EXTERNAL_CODE:
                      if(isAllGranted(grantResults)){
                          onWriteExternalGranted();
                      }else{
                          onWriteExternalDenied();
                      }
                  break;
              }
          }
      
          private boolean isAllGranted(int[] grantResults) {
              for(int result : grantResults){
                  if(result != PackageManager.PERMISSION_GRANTED){
                      return false;
                  }
              }
              return true;
          }
      
          protected void onWriteExternalDenied() {}
      
          protected void onWriteExternalGranted(){};
      }
    
  • MainActivity 继承 BaseActivity,实现在download目录下新建一个文件

    判断是否有权限。有,直接操作,没有,请求权限。

      if(hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
              Manifest.permission.READ_EXTERNAL_STORAGE)){
          doCreateFile(); // 新建文件具体实现
      }else{
          requestPermission(Constants.WRITE_EXTERNAL_CODE,
                  Manifest.permission.WRITE_EXTERNAL_STORAGE,
                  Manifest.permission.READ_EXTERNAL_STORAGE);
      }
    

    复写成功失败方法

      @Override
      protected void onWriteExternalDenied() {
          Snackbar.make(fabSD, "获取文件权限失败", Snackbar.LENGTH_SHORT).show();
      }
    
      @Override
      protected void onWriteExternalGranted() {
          doCreateFile();
      }
    

    这样虽然没有一个权限申请都需要复写一套成功失败的回调,但已经简洁了很多,而且加上注释逻辑也很清晰

  • 第三方库实现 录音权限申请

    也可以借用第三方的库来实现,这里采用的是一个注解库

  • 使用方法

    加入引用

      compile 'com.lovedise:permissiongen:0.0.6'
    

    请求权限

      PermissionGen.needPermission(this, Constants.RECORD_AUDIO,
              new String[]{
                      Manifest.permission.RECORD_AUDIO
              });
    

    在onRequestPermissionsResult注册该库的方法。

      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          PermissionGen.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
      }
    

    成功回调

      @PermissionSuccess(requestCode = Constants.RECORD_AUDIO)
      public void doRecordSounds(){
          Snackbar.make(fabMic, "录音中...", Snackbar.LENGTH_SHORT).show();
      }
    

    失败回调

      @PermissionFail(requestCode = Constants.RECORD_AUDIO)
      public void onPremissionDenied(){
          Snackbar.make(fabMic, "没有录音权限", Snackbar.LENGTH_SHORT).show();
      }
    

    最后,第三方库虽然使用方便,但注解时反射会影响运行时的速度。使用时需要考虑。

Constants.java

public class Constants {
    public static final int WRITE_EXTERNAL_CODE = 0x000;
    public static final int CALL_PHONE = 0x001;
    public static final int RECORD_AUDIO = 0x002;
}

本文总结自qandroid老师慕课网Android 6.0新特性课程。###

然后你们最爱的源码###

你可能感兴趣的:(Android 6.0 权限机制等新特性)