最新消息:欢迎访问Android开发中文站!商务联系微信:loading_in

Android6.0权限管理-PermissionsDispatcher

开发进阶 loading 1971浏览 0评论

新的运行时权限仅当我们设置targetSdkVersion to 23才起作用,app在6.0之前的设备依然使用旧的权限系统。

如果app的targetSdkVersion 低于 23,那将被认为app没有用23新权限测试过,那将被继续使用旧有规则:用户在安装的时候不得不接受所有权限,安装后app就有了那些权限!然后app像以前一样可以正常运行!注意,此时用户依然可以取消已经同意的授权!用户取消授权时,android 6.0系统会警告,但这不妨碍用户取消授权。
问题又来了,这时候你的app崩溃了!
同一组的任何一个权限被授权了,其他权限也自动被授权。

权限组列表:

Permission Group Permissions
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

当用户安装或更新应用时,系统将授予应用所请求的属于 PROTECTION_NORMAL 的所有权限(安装时授权的一类基本权限)。这类权限包括:

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.android.launcher.permission.UNINSTALL_SHORTCUT
只需要在AndroidManifest.xml中简单声明这些权限就好,安装时就授权。不需要每次使用时都检查权限,而且用户不能取消以上授权。
好了,下面我们来使用PermissionsDispatcher进行管理Android权限。
Annotation Required Description
@RuntimePermissions Register an Activity or Fragment to handle permissions/

 ps:在Activity或者Fragment中需要添加,来处理权限的问题
@NeedsPermission Annotate a method which performs the action that requires one or more permissions/

ps:该方法需要哪些权限,当用户授予了权限之后,会调用使用此注解的方法
@OnShowRationale Annotate a method which explains why the permission/s is/are needed. It passes in a PermissionRequest object which can be used to continue or abort the current permission request upon user input/

ps:简单的来说就是为什么需要此权限,这需要展现给用户,而用户可以选择“继续”或者“中止”当前的权限许可请求
@OnPermissionDenied Annotate a method which is invoked if the user doesn’t grant the permissions/

ps:如果用户不授予某权限时调用的方法,
@OnNeverAskAgain Annotate a method which is invoked if the user chose to have the device “never ask again” about a permission/

ps:如果用户选择了让设备“不再询问”,而调用的方法
比如我们在MainActivity中使用,那么我们的MainActivity应该是这样的:
 
@RuntimePermissions  
public class MainActivity extends AppCompatActivity implements Runnable{  

@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)  
void doACacheNeedsPermission() {  
//处理当用户允许该权限时需要处理的方法  
}  
@OnShowRationale(Manifest.permission.READ_EXTERNAL_STORAGE)  
void ACacheShowRationale(PermissionRequest request) {  
    request.proceed(); // 提示用户权限使用的对话框  
}  

@OnNeverAskAgain(Manifest.permission.READ_EXTERNAL_STORAGE)  
void ACacheOnNeverAskAgain() {  
Toast.makeText(this, "ACacheOnNeverAskAgain, Toast.LENGTH_SHORT).show();  
}  

/** 
 * 如果用户拒绝该权限执行的方法 
 */  
@OnPermissionDenied(Manifest.permission.READ_EXTERNAL_STORAGE)  
void ACacheOnPermissionDenied() {  
    Toast.makeText(this, "ACacheOnPermissionDenied", Toast.LENGTH_SHORT).show();  
}  
/** 
 * 权限请求回调,提示用户之后,用户点击“允许”或者“拒绝”之后调用此方法 
 * @param requestCode  定义的权限编码 
 * @param permissions 权限名称 
 * @param grantResults 允许/拒绝 
 */  
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
    MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);  
}  

}

我们看到了该Activity继承了AppCompatActivity,是的,如果使用PermissionsDispatcher进行权限管理,那么Activity就要继承AppCompatActivity。这就要使用到了兼容包里的类了。同样此时相应Activity中使用的主题,也需要进行修改,修改成相应兼容包里的主题。

那么我们来看看MainActivityPermissionsDispatcher类中是如何实现权限管理的,默认是没有此类的,需要编译下才会有此类。

 
final class MainActivityPermissionsDispatcher {  
  //定义的权限编码,当PERMISSION_DOACACHENEEDSPERMISSION有N个权限,那么REQUEST_DOACACHENEEDSPERMISSION就会有多少值  
  private static final int REQUEST_DOACACHENEEDSPERMISSION = 1;  

  //需要请求的权限名称  
  private static final String[] PERMISSION_DOACACHENEEDSPERMISSION = new String[] {"android.permission.READ_EXTERNAL_STORAGE"};  

  private MainActivityPermissionsDispatcher() {  
  }  
  /** 
   * 检查用户设备是否拥有该权限 
   * @param target  
   */  
  static void doACacheNeedsPermissionWithCheck(MainActivity target) {  
    // 如果拥有该权限,那么调用用户注解为:@NeedsPermission的方法  
    if (PermissionUtils.hasSelfPermissions(target, PERMISSION_DOACACHENEEDSPERMISSION)) {  
      target.doACacheNeedsPermission();  
    } else {  
      // 如果用户设备没有该权限,那么请求提示用户是否赋予该权限  
      if (PermissionUtils.shouldShowRequestPermissionRationale(target, PERMISSION_DOACACHENEEDSPERMISSION)) {  
        target.ACacheShowRationale(new DoACacheNeedsPermissionPermissionRequest(target));  
      } else {  
        ActivityCompat.requestPermissions(target, PERMISSION_DOACACHENEEDSPERMISSION, REQUEST_DOACACHENEEDSPERMISSION);  
      }  
    }  
  }  
  /** 
   * 权限请求回调 
   * @param target 
   * @param requestCode 权限编码 
   * @param grantResults 
   */  
  static void onRequestPermissionsResult(MainActivity target, int requestCode, int[] grantResults) {  
    switch (requestCode) {  
      case REQUEST_DOACACHENEEDSPERMISSION:  
      if (PermissionUtils.getTargetSdkVersion(target) < 23 && !PermissionUtils.hasSelfPermissions(target, PERMISSION_DOACACHENEEDSPERMISSION)) {  
        target.ACacheOnPermissionDenied();  
        return;  
      }  
      if (PermissionUtils.verifyPermissions(grantResults)) {  
        target.doACacheNeedsPermission();  
      } else {  
        if (!PermissionUtils.shouldShowRequestPermissionRationale(target, PERMISSION_DOACACHENEEDSPERMISSION)) {  
          target.ACacheOnNeverAskAgain();  
        } else {  
          target.ACacheOnPermissionDenied();  
        }  
      }  
      break;  
      default:  
      break;  
    }  
  }  

  private static final class DoACacheNeedsPermissionPermissionRequest implements PermissionRequest {  
    private final WeakReference<MainActivity> weakTarget;  

    private DoACacheNeedsPermissionPermissionRequest(MainActivity target) {  
      this.weakTarget = new WeakReference<>(target);  
    }  

    @Override  
    public void proceed() {  
      MainActivity target = weakTarget.get();  
      if (target == null) return;  
      ActivityCompat.requestPermissions(target, PERMISSION_DOACACHENEEDSPERMISSION, REQUEST_DOACACHENEEDSPERMISSION);  
    }  

    @Override  
    public void cancel() {  
      MainActivity target = weakTarget.get();  
      if (target == null) return;  
      target.ACacheOnPermissionDenied();  
    }  
  }  
}

那么如果需要使用PermissionsDispatcher,需要在project的 build.gradle中添加

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

然后在app module中的build.gradle中添加:(必须在app module中添加)

apply plugin: 'android-apt'  

dependencies {  
  compile 'com.github.hotchemi:permissionsdispatcher:${latest.version}'  
  apt 'com.github.hotchemi:permissionsdispatcher-processor:${latest.version}'  
}

目前${latest.version} 最新的是2.0.8。

最后奉上该库的github地址:https://github.com/hotchemi/PermissionsDispatcher

好了,PermissionsDispatcher的使用基本如此。希望可以帮助到大家,如果有不对的地方还望提出。

转载请注明:Android开发中文站 » Android6.0权限管理-PermissionsDispatcher

您必须 登录 才能发表评论!