Introduction:
This article mainly explains the Android permission management aspects of several points:
-
Android permissions background knowledge;
-
Authority check and authority compatibility;
-
The APP management permission page is displayed
First, Android permissions background knowledge
When it comes to Android permission management, insiders know that Google put forward the runtime permission management mechanism in Android 6.0. Before Android 6.0, the permissions applied only need to be listed in Androidmanifest.xml, which is easy to cause some security risks. Therefore, in Android 6.0, Google proposed a new permission management mechanism (official website: Working with System Permissions) to better protect user privacy, and divided it into two categories:
(1) Normal Permissions
Normal Permissions generally do not involve user privacy and do not require user authorization, such as mobile phone vibration and network access.
(2) Dangerous Permission
Dangerous Permission generally involves user privacy and requires user authorization (dynamic application), such as reading SIM card status, accessing address book, and reading and writing SD cards.
Adb shell PM list permissions -d -g
Dangerous Permission group
As shown above: Dangerous Permissions generally exist in the form of Permission groups. As long as one of the permissions in the group is Granted, All permissions under the Permission group are Granted (for now, the rule may change later).
2. Permission check and permission compatibility
This section describes how to perform permission check and permission compatibility. The operations are classified into the following types:
(1) targetSdkVersion>=23, terminal device is 6.0 (API 23) or above system;
Do not obtain permissions during installation. Apply for permissions from users during runtime. This part of the permission check is simpler, does not involve permissions compatible, using official scheme can, using the Context: : checkSelfPermisson, it is recommended to use ContextCompat: : checkSelfPermisson check permissions can, general inspection process is as follows:
-
Determine whether there is a corresponding permissions (ContextCompat: : checkSelfPermisson)
-
Determine whether to explain to corresponding permission to use (ActivityCompat: : shouldShowRequestPermissionRationale) if the need to explain, is real custom permissions interface
-
Don’t need to explain, direct request corresponding permissions (ActivityCompat: : requestPermissions)
The above situation is relatively simple and will not be repeated here.
(2) targetSdkVersion<23, terminal device is 6.0 (API 23) or above system;
The old permissions mechanism is used. Permissions in the Androidmanifest.xml file will be asked when the app is installed, but users can turn off related permissions in the Settings list, which may affect the normal operation of the app.
(3) Terminal system less than 6.0 (API 23)
If the terminal system is smaller than 6.0, do you still need to consider it? It must be the old permission management mechanism. When the app is installed, the permissions in the Androidmanifest.xml file will be asked, and the user cannot close it.
The answer is negative, in the actual measurement found that there are many domestic Rom mobile phones in 6.0 before the switch to close the authority. This situation is also our compatible object.
Now penguin FM supports streaming free, and it needs to use READ_PHONE_STATE permission (reading SIM card status). Since we have not made relevant judgment on whether the permission is closed before, we have received many cases of streaming free failure due to the closure of the above permission.
The adaptation process is as follows:
(1) Use try catch to check whether permission is closed
The idea is simple, if the user forbids the change of permission, it will definitely be an exception, so you can use catch, but it turns out that it doesn’t work, why? Because a method using the READ_PHONE_STATE privilege has an internal try catch that cannot be caught outside, the method is invalidated.
(2) ContextCompat: : checkSelfPermisson
Since 6.0 you can use the Context: : checkSelfPermisson permission check, it can use the support ContextCompat in v4: : checkSelfPermisson method, try to find the API 23 the following failure, In order to explore the reason, reviewed the ActivityCompat: : requestPermissons internal implementation, as follows
ActivityCompat::requestPermissons
23 the following internal permission check methods in the API, use the PackageManager: : checkPermission, to view the PackageManager: : checkPermission method, as follows: Androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: Androidmanifest.xml: Androidmanifest.xml: Androidmanifest.xml
PackageManager::checkPermission
Support V4 has a tool class called PermissionChecker for checking permissions.
(3) the PermissionChecker
PermissionChecker actually uses AppOpsManagerCompt inside PermissionChecker. AppOpsManager was added to API 19.
PermissionChecker::checkPermission
Then look at the internal implementation of AppOpsManagerCompat
AppOpsManagerCompat::permissionToOp
The IMPL implementation is as follows:
IMPL implementation
As can be seen from the above picture: Under API 23, AppOpsManagerImpl: : permissionToOp directly returns null, 23 the following permission check this led directly to the API will return granted, therefore, the method under the API 23, permission check method will fail.
(4) AppOpsManager
Above API 19, Google officially provides the AppOpsManager class to check permissions. When you see this API, you will think of “God always has a way”. There are two important methods: AppOpsManager::checkOp(int op,int uid,String packageName) (hide method) and AppOpsManager::checkOp(String op,int uid,String PackageName) (public method, API 23 above available), without thinking, directly write the following two methods
1) AppOpsManager::checkOp(int op,int uid,String packageName)
Need to use reflection:
AppOpsManager::checkOp(int op ,int uid ,String packageName)
2)AppOpsManager::checkOp(String op,int uid ,String packageName)
API >= 23 can be used:
AppOpsManager::checkOp(String op,int uid ,String packageName)
When API is lower than 23, OP_READ_PHONE_STATE =51 cannot be found, resulting in reflection failure.
6.0 (API 23) _NUM_OP = 62
6.0 (API 23 )_NUM_OP = 62
Is it possible that each version is different? Check out the other versions to verify this idea:
5.1.1 (API 22 )_NUM_OP = 48
5.1.1
Op number limit (need to find the corresponding source note **) see:
Check the Android version _NUM_OP (currently 5.1.1 is supported at most)
At this point, OP_READ_PHONE_STATE = 51 is below 6.0 (API 23) and cannot be found by reflection, so READ_PHONE_STATE permission checks are limited to 6.0 and above.
The AppOpsManager class is not designed for developers, but other permissions can use this method, the presupposition is to see what version of OP_* is available, need to do compatibility scheme.
public class AppOpsManager
extends Object
API for interacting with “application operation” tracking.
This API is not generally intended for third party application developers; most features are only available to system applications. Obtain an instance of it through Context.getSystemService with Context.APP_OPS_SERVICE.
(5) Finally checked several third-party permission libraries (not finished yet)
-
PermissionsDispatcher
-
AndPermission
3. Jump to app management permission page
Since here explains the jump to the APP management permissions page method, can think of it, things are definitely not too easy. Android fragmentation exists not only in UI adaptation, but also here, preventing us from using the same way to jump to the app management permissions page (adaptation, a constant pain in Android development).
Is there any way to simplify the adaptation work and reduce the amount of development? Of course, there are methods, but we need to summarize and explore by ourselves. At present, there are methods:
(1) Directly jump to the system setting page
Intent intent =newIntent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package",getPackageName(), null)); try{ startActivity(intent); }catch(Exception exception) { exception.printStackTrace(); }
Copy the code
Make sure you add a try catch, otherwise you might crash. This method does not need to adapt to different versions of ROM from different manufacturers. The disadvantage is that users can only go to the system Settings page and then go to the corresponding APP permission management (there are always some users who cannot find it).
(2) Stand on the shoulders of our predecessors
Quoting previous experience: Mobile phones of major Android mobile brands jump to the permission management interface (not verified, after all, there are not so many mobile phones)
It may have been true at that time, but it may not work now. Now take MIUI jumping to app permission management page as an example to illustrate.
1) beautiful MIUI 6/7
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR"); localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity"); localIntent.putExtra("extra_pkgname", context.getPackageName()); try{ startActivity(intent); }catch(Exception exception) { exception.printStackTrace(); }
Copy the code
2) beautiful MIUI 8
Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR"); localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity"); localIntent.putExtra("extra_pkgname", context.getPackageName()); try{ startActivity(intent); }catch(Exception exception) { exception.printStackTrace(); }
Copy the code
Comparing 1) and 2), we find that on MIUI6/7 and MIUI8, the name of the permission management page of the activity is different, so using miUI6/7 will fail on MIUI8. If there is no try catch added, it will crash directly.
For these changes, as a developer is usually don’t know, even through feedback found this problem, also don’t know what the corresponding activity is likely, at the moment or scouring online have a similar solution, or turn to the corresponding ROM developers developers BBS (sometimes solve the response speed is quite slow). Is there a better way? Please refer to section (3) for details.
(3) View the activity of the permission management page of a certain version of a ROM
Huawei P8 is used as an example. The steps are as follows:
1) Find the permission management page of the corresponding APP through the Settings as follows:
Penguin FM rights management page on huawei P8
2) Find the activity on the corresponding page
Method 1: Use the Add tool to view activities at the top of the stack
adb shell dumpsys activity | grep "mFocusedActivity"
Copy the code
Penguin FM corresponds to the activity on the rights management page of Huawei P8
More detailed stack information
Detailed stack information
Method 2: Use the Activity Tracer tool
How to use it: See my previous article: Android Development: Small Tools, Big Efficiency
Use the Activity Tracer to view the Activity corresponding to the permission management page
Reference article (copy link to open in browser) :
Working with System Permissionshttps://developer.android.com/training/permissions/index.html
View the corresponding version of the Android _NUM_OPhttp: / / grepcode.com/search?query=android.app.AppOpsManager&n=
PermissionsDispatcherhttps://github.com/hotchemi/PermissionsDispatcher
AndPermissionhttps://github.com/yanzhenjie/AndPermission
The major Android mobile phone brand mobile phone jump to rights management interface at http://www.jianshu.com/p/b5c494dba0bc
Android development — small tools, big efficiency (click here to read the original can jump) http://www.jianshu.com/p/672d64fdc486
If you think our content is good, please forward it to moments and share it with your friends