Starting from Android6.0, The Android system provides the mechanism of dynamic application for permissions. When the APP uses dangerous permissions, the user’s authorization is required for further operations.

Permission Application Mode

There are two ways to apply for permissions in the Android system, as shown in the following figure:

Static application

Android6.0 systems (API < 23) take this approach, as long as the user registered permissions in androidmanifest.xml, after installing the APP, they get these permissions by default. This authorization method has very low security. If the user does not close the corresponding permission after installation, the user’s private data is easy to be stolen by some junk apps. In order to solve this problem, the major domestic mobile phone manufacturers for Android5.0 system, for some permissions to do certain restrictions, even in Android5.0, also need users to manually authorize to use, which to some extent improves security, but also because there is no unified standard, thus there are various compatibility problems.

Dynamic application

With the upgrade of the system, Google has also realized the disadvantages of static permission application, so in Android6.0, the permissions are sorted out again, and the permissions are divided into common permissions and dangerous permissions:

  • Normal permissions: permissions that do not compromise user privacy and are automatically granted as long as the developer is registered in androidmanifest.xml.
  • Dangerous permissions: permissions to access a user’s private data that must be granted with the user’s consent;
Summary of Risk Permissions

In Android development, we should use isolated permission application whenever possible, so that users can block the corresponding functions when they are not authorized. APP, now a lot of content users in didn’t see anything, you need a variety of access, is not available without permission, it may cause the user, of course, also is a kind of impact to users a sense of security, time is long, users might think that using the APP should be authorized, so as to give some malicious APP to do evil.

Dynamic permission application process

Core API Introduction

Check whether the permission has been obtained:

// ContextCompat.java
public static int checkSelfPermission(@NonNull Context context, @NonNull String permission)

// PermissionChecker.java
public static int checkSelfPermission(@NonNull Context context,
            @NonNull String permission)
Copy the code

These two methods are the methods that check access permissions, but ContextCompat checkSelfPermission in some systems, such as based on SMS Android8.0 MIUI10 check permissions) has a bug, cannot accurately judge whether permissions has access to, At that point can be combined with PermissionChecker. CheckSelfPermission judge, so whether permissions have access can be realized by using the following:

public static boolean hasPermission(@NonNull Context context, @NonNull String permission) { if (ContextCompat.checkSelfPermission(context, permission) ! = PackageManager.PERMISSION_GRANTED || PermissionChecker.checkSelfPermission(context, permission) ! = PackageManager.PERMISSION_GRANTED) { return false; } return true; }Copy the code

To apply for permission

When a request to the system is not obtained, use the requestPermissions method:

Public static void requestrequestpermissions (final @requestnull) final @NonNull String[] permissions, Final @intrange (from = 0) int requestCode) // Fragment. Java // Request permission in the Fragment public final void requestPermissions(@NonNull String[] permissions, int requestCode)Copy the code

Used in fragments ActivityCompat requestPermissions right limit, if the user refused (and to cancel the tip) no longer request, fragments of onRequestPermissionsResult will not be back, The user cannot be instructed to open permissions. The Fragment member method requestPermissions should be used in the Fragment to requestPermissions.

Check whether the APP should show the explanation used to apply for permissions

/ / ActivtyCompat. Java / / check whether the APP should be explained to for apply for permission to show the public static Boolean shouldShowRequestPermissionRationale (@ NonNull Activity Activity, @nonnull String Permission);Copy the code

The return value of this method is interpreted as follows:

  • If APP has never applied for the specified permission or has applied for the specified permission, but is rejected by the user and “prompt no more” is checked, false is returned.
  • APP is rejected by the user when applying for enactment right, but [prompt no longer] is not selected, which returns true

Therefore, when using this method, we should first determine whether the APP has applied for permission, otherwise it is difficult to determine the two cases of returning false.

Callback result of permission request

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
Copy the code

This is the result callback method for requesting permissions in activities and Fragments, where permissions represent the array of requested permissions and grantResults represent the requested results for each permission. Values are:

Public static final int PERMISSION_GRANTED = 0; Public static final int PERMISSION_DENIED = -1;Copy the code

Generally, the processing logic after permission application is implemented in this method.

Implementation of dynamic permission application

Conditions for dynamic permission application:

  • TargetSdkVersion > = 23;
  • Android version 6.0 or later;

For the case that the above conditions cannot be met at the same time, the default mode of static permission application is used. However, different ROMs may modify their mechanism for security, so there may be differences due to different ROMs.

After knowing the core API of applying for permission, we will introduce the realization process of applying for permission in the Activity. Click apply for permission to take photos as an example.

private void startPhoto() { if (hasPermission(this, New String [] {the Manifest. Permission. CAMERA})) {/ / the pictures of the execution logic} else {ActivityCompat. RequestPermissions (context, rnew String[]{Manifest.permission.ACCESS_FINE_LOCATION}), PERMISSION_REQUEST_CODE); }}Copy the code

Then in onRequestPermissionsResult monitored access application results:

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); If (hasPermission (permissions)) {/ / the pictures of the execution logic} else {the if (ActivityCompat. ShouldShowRequestPermissionRationale (context, Permissions [refusedPermissionIndex])) {} else {// add permissions to the user}}Copy the code

The above is just a basic process of applying for permissions, the real implementation should consider the problem of multiple permissions, version compatibility, ROM compatibility and so on.

Of course, this code is not written in every Activity/Fragment that requires permission in development. Even if it is packaged as a tool class, it needs to be referenced in every Activity/Fragment, which is too coupling. It is often possible to apply for permissions in a transparent Activity so that when applying for permissions, you can jump directly to the Activity. A dynamic permission application library is recommended for your reference.

PermissionManager

PermissionManager is an open source library for dynamically requesting permissions based on an AOP implementation, with the goal of making the process easier. Of course, it can also be used as a reference project for learning About Aspectj. Has the following advantages:

  • Multiple permission applications are supported.
  • Easy to use, one line annotation to achieve permission application
  • Provides extensible permission descriptions and boot Settings;
  • Provides blocking/non-blocking application methods;

For details, please refer to the source address: PermissionManager

conclusion

Due to the serious fragmentation of Android, various domestic manufacturers have made different processing of permissions, so there must be failure in dynamic application. If you find problems when using PermissionManager, please feel free to issue & pull Request.