對於動態權限,大家應該都不陌生了,在Android6.0版本加入了動態權限的概念,在Android 6.0之前申明權限只需要在AndroidManifest清單中註冊相應權限就可以;Android 6.0以上系統就需要根據權限的等級(普通權限和危險權限)進行權限註冊,如果是普通權限還是依照之前的處理方式直接在AndroidManifest清單中註冊即可,但是危險權限不僅需要在AndroidManifest清單中註冊且還需要在使用時動態申請;
權限分級清單見
https://yilanjingwang.blog.csdn.net/article/details/102992896
其實現在主流權限管理框架有三個,分別爲PermissionsDispatcher、RxPermissions(基於RxJava)和easypermissions(谷歌出品,必是XX);但是我比較推薦使用PermissionsDispatcher(因爲它使用起來更簡單,尤其是配合插件使用)。
添加依賴:
java:
dependencies {
implementation "org.permissionsdispatcher:permissionsdispatcher:${latest.version}"
annotationProcessor "org.permissionsdispatcher:permissionsdispatcher-processor:${latest.version}"
}
With Kotlin(advance with the times):
apply plugin: 'kotlin-kapt'
dependencies {
implementation "org.permissionsdispatcher:permissionsdispatcher:${latest.version}"
kapt "org.permissionsdispatcher:permissionsdispatcher-processor:${latest.version}"
}
另外如果還沒用AndroidX的請用3.x的版本。
安裝PermissionsDispatcher插件
install之後restart(如果找不到位置,請自行百度……)
使用插件的方式很簡單,在activity/fragment中右鍵
Usage with Kotlin
Here’s a minimum example, in which you register a MainActivity which requires Manifest.permission.CAMERA.
0. Prepare AndroidManifest
Add the following line to AndroidManifest.xml:
1. Attach annotationsPermissionsDispatcher introduces only a few annotations, keeping its general API concise:
NOTE: Annotated methods must not be private.
Annotation | Required | Description |
---|---|---|
@RuntimePermissions | ✓ | Register an Activity or Fragment to handle permissions |
@NeedsPermission | ✓ | Annotate a method which performs the action that requires one or more permissions |
@OnShowRationale | Annotate a method which explains why the permissions are needed. It passes in a PermissionRequest object which can be used to continue or abort the current permission request upon user input. If you don’t specify any argument for the method compiler will generate process{NeedsPermissionMethodName}ProcessRequest. You can use those methods in place of PermissionRequest(ex: with DialogFragment) | |
@OnPermissionDenied | Annotate a method which is invoked if the user doesn’t grant the permissions | |
@OnNeverAskAgain | Annotate a method which is invoked if the user chose to have the device “never ask again” about a permission |
@RuntimePermissions
class MainActivity : AppCompatActivity(), View.OnClickListener {
@NeedsPermission(Manifest.permission.CAMERA)
fun showCamera() {
supportFragmentManager.beginTransaction()
.replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
.addToBackStack("camera")
.commitAllowingStateLoss()
}
@OnShowRationale(Manifest.permission.CAMERA)
fun showRationaleForCamera(request: PermissionRequest) {
showRationaleDialog(R.string.permission_camera_rationale, request)
}
@OnPermissionDenied(Manifest.permission.CAMERA)
fun onCameraDenied() {
Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show()
}
@OnNeverAskAgain(Manifest.permission.CAMERA)
fun onCameraNeverAskAgain() {
Toast.makeText(this, R.string.permission_camera_never_askagain, Toast.LENGTH_SHORT).show()
}
}
- Delegate to generated functions
Now generated functions become much more concise and intuitive than Java version!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById(R.id.button_camera).setOnClickListener {
// NOTE: delegate the permission handling to generated function
showCameraWithPermissionCheck()
}
}
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)
}
Usage with Java
Here’s a minimum example, in which you register a MainActivity which requires Manifest.permission.CAMERA.
0. Prepare AndroidManifest
Add the following line to AndroidManifest.xml:
1. Attach annotationsPermissionsDispatcher introduces only a few annotations, keeping its general API concise:
NOTE: Annotated methods must not be private.
Annotation | Required | Description |
---|---|---|
@RuntimePermissions | ✓ | Register an Activity or Fragment to handle permissions |
@NeedsPermission | ✓ | Annotate a method which performs the action that requires one or more permissions |
@OnShowRationale | Annotate a method which explains why the permissions are needed. It passes in a PermissionRequest object which can be used to continue or abort the current permission request upon user input. If you don’t specify any argument for the method compiler will generate process{NeedsPermissionMethodName}ProcessRequest. You can use those methods in place of PermissionRequest(ex: with DialogFragment) | |
@OnPermissionDenied | Annotate a method which is invoked if the user doesn’t grant the permissions | |
@OnNeverAskAgain | Annotate a method which is invoked if the user chose to have the device “never ask again” about a permission |
@RuntimePermissions
public class MainActivity extends AppCompatActivity {
@NeedsPermission(Manifest.permission.CAMERA)
void showCamera() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
.addToBackStack("camera")
.commitAllowingStateLoss();
}
@OnShowRationale(Manifest.permission.CAMERA)
void showRationaleForCamera(final PermissionRequest request) {
new AlertDialog.Builder(this)
.setMessage(R.string.permission_camera_rationale)
.setPositiveButton(R.string.button_allow, (dialog, button) -> request.proceed())
.setNegativeButton(R.string.button_deny, (dialog, button) -> request.cancel())
.show();
}
@OnPermissionDenied(Manifest.permission.CAMERA)
void showDeniedForCamera() {
Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show();
}
@OnNeverAskAgain(Manifest.permission.CAMERA)
void showNeverAskForCamera() {
Toast.makeText(this, R.string.permission_camera_neverask, Toast.LENGTH_SHORT).show();
}
}
- Delegate to generated class
Upon compilation, PermissionsDispatcher generates a class for MainActivityPermissionsDispatcher([Activity Name] + PermissionsDispatcher), which you can use to safely access these permission-protected methods.
The only step you have to do is delegating the work to this helper class:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button_camera).setOnClickListener(v -> {
// NOTE: delegate the permission handling to generated method
MainActivityPermissionsDispatcher.showCameraWithPermissionCheck(this);
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// NOTE: delegate the permission handling to generated method
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}