From Android 6 From 0, the Android system provides a mechanism for dynamically applying for permission. When using dangerous permission, the APP needs the user's authorization before further operation.
Permission application method
There are two ways of permission application in Android system, as shown in the figure below:
Static application
Android6. The system before 0 (API < 23) adopts this method, as long as the user is in androidmanifest Permissions are registered in the XML. After installing the APP, these permissions are obtained by default. The security of this authorization method is extremely low. If the user does not close the corresponding permissions after installation, the user's private data is easy to be stolen by which spam apps. In order to solve this problem, the major domestic mobile phone manufacturers are Android 5 For systems below 0, certain permissions are limited, even in Android 5 Below 0, users also need manual authorization to use it, which improves the security to some extent, but there are various compatibility problems due to the lack of unified standards.
Dynamic application
With the upgrade of the system, Google is also aware of the disadvantages of static application permission, so in Android 6 0, the permissions are reorganized and divided into ordinary permissions and dangerous permissions:
- Normal permission: permission that will not bring danger to user privacy, as long as the developer is in Android manifest If it is registered in XML, the system will automatically authorize it. As follows:
<!-- PHONE_STATE jurisdiction--> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- network right--> <uses-permission android:name="android.permission.INTERNET" />
- Dangerous authority: the authority to access the user's private data. The interactive interface needs to pop up, and the authorization can be obtained only with the user's consent;
Summary of hazard authority
In Android development, we should use isolated application permission as much as possible, and shield the corresponding functions when users do not have authorization. Now, many content apps require various permissions if users don't see anything when they go in. They can't use them without permissions, which may cause users' disgust. Of course, it is also an impact on users' security awareness. Over time, users may feel that they should be authorized to use apps, thus giving some malicious apps room 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 code
Both methods are methods to check whether permission is obtained, but contextcompat There is a bug in checkselfpermission on some systems (such as when checking SMS permission based on MIUI10 of Android 8.0), which can not accurately judge whether the permission has been obtained. At this time, it can be combined with permissionchecker Checkselfpermission is used to judge whether the permission has been obtained. The following methods can be used to judge whether the permission has been obtained:
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; }
Apply for permission
When permission is not obtained, you need to request from the system. When requesting, use the requestPermissions method:
// ActivityCompat.java // Request permission in Activity public static void requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) // Fragment.java // Apply for permission in Fragment public final void requestPermissions(@NonNull String[] permissions, int requestCode)
Using activitycompat. In Fragment When requestPermissions applies for permission, if the user rejects the request (and checks no more prompt), onRequestPermissionsResult in the Fragment will not be recalled, and the user cannot be guided to open permission. Therefore, the permission of the request member should be used in the Fragment permission method.
Check whether the APP should be used to show the explanation of the application permission
// ActivtyCompat.java // Check whether the APP should show the user the explanation of applying for permission public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission);
The return value of this method is explained as follows:
- When the APP has never applied for the specified permission or applied for the specified permission, but is rejected by the user, and [no more prompt] is checked, false is returned;
- When APP applies for specified permission, it is rejected by the user, but [don't prompt again] is not checked, which returns true
Therefore, when using this method, we must first judge whether the APP has applied for permission, otherwise it is difficult to judge the two cases that return false.
Callback of request permission result
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
This is the result callback method of requesting permission in Activity and Fragment, where permissions represents the requested permission array and grantResults represents the request result of each permission. The value is:
// Obtain authorization public static final int PERMISSION_GRANTED = 0; // Unauthorized public static final int PERMISSION_DENIED = -1;
Generally, the processing logic after applying for permission is implemented in this method.
Implementation of dynamic permission application
Conditions for dynamic permission application:
- targetSdkVersion >= 23;
- Android system version is 6.0 or above;
If the above conditions cannot be met at the same time, the static permission application method is used by default, but the mechanism may be modified for the sake of security in different ROMs, so it may be different due to different ROMs.
After understanding the core API of applying for permission, let's introduce the implementation process of applying for permission in Activity. Let's take clicking to apply for photo permission as an example:
private void startPhoto() { if (hasPermission(this, new String[]{Manifest.permission.CAMERA})) { // Execute the logic of taking pictures } else { ActivityCompat.requestPermissions(context, rnew String[]{Manifest.permission.ACCESS_FINE_LOCATION}), PERMISSION_REQUEST_CODE); } }
Then listen for the result of permission application in onRequestPermissionsResult:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (hasPermission(permissions)) { // Execute the logic of taking pictures } else { if (ActivityCompat.shouldShowRequestPermissionRationale(context, permissions[refusedPermissionIndex])) { // Show the user the reason for applying for permission } else { // Reference user to open permission } } }
The above is just a basic process of applying for permission. In the real implementation, we should also consider the problems of multiple permissions, version compatibility, ROM compatibility, etc.
Of course, this code will not be written in each Activity/Fragment that needs to apply for permission in development. Even if it is encapsulated into a tool class, it needs to be referenced in each Activity/Fragment, which is too coupled. Generally, permission application can be implemented in a transparent Activity. In this way, when applying for permission, you can directly jump to the Activity. The following recommends a library for dynamic permission application for reference.
PermissionManager
PermissionManager is an open source library for dynamic permission application based on AOP. The purpose is to make the process of permission application easier. Of course, it can also be used as a reference project for learning Aspectj. It has the following advantages:
- Support multi permission application;
- It is simple and easy to use, and the permission application is realized by one line of annotation
- It provides extensible permission description and guidance setting mode;
- Provide blocking / non blocking application methods;
For specific introduction, please refer to its source code address: PermissionManager