It was first posted on my official account

About Dynamic Permissions

1. A few concepts need to be clarified before you upgrade your app with dynamic permissions

1.1 API level corresponding to version number

Check out the official website

1.2, minSdkVersion, targetSdkVersion and compileSdkVersion

These properties are normally configured in Gradle defaultConfig to do the following

(1) minSdkVersion specifies the minimum API level required for the application to run. If the system API level is lower than minSdkVersion, android will prevent users from installing the application. If not specified, the default is 1. If you use an API that changes the level of the API in your project, an error will be reported during compilation. You can see that this property takes effect not only when the program is installed, but also when the project is built

(2) the targetSdkVersion

An integer that specifies the application’s target API level, which if not set defaults to the same as minSdkVersion. This property tells the system that the application has been tested against the target version and that the system does not need to use compatibility mode to make your application forward compatible with the target version. If targetSdkVersion is 19 (corresponding to Android4.4), the application can only use the new features of API 19 when running. Even if API 23’s new feature is used in your code, it will not be used at runtime. The targetSdkVersion attribute is used at runtime to determine whether to run the program in compatible mode. For example, Android6.0 has added dynamic permissions. Blindly set your targetSDKVersion to 23(6.0) and exceptions will occur where permissions are required. To do this, before you apply for dynamic permissions, you need to set the target version to be lower than 23 in order for your APP to run properly.

(3) the complieSdkVersion

CompileSdkVersion simply tells Gradle which VERSION of the SDK to use to compile the application. This will not be included in apK and will not affect the running result of the application. It doesn’t make a difference but

CompileSDKVersion deals with the compiler, minSDKVersion and targetSDKVersion with the system.

2. How to upgrade the dynamic permissions of app

First, you need to understand the concept of dynamic permissions

2.1 Dynamic Rights

This is proposed in Android 6.0. From this version, users can grant or revoke application permissions when they are running rather than when the application is installed. Corresponding to API23, the most important change in this version is the dynamic management of permissions. You can obtain permissions from the command line through the ADB tool

List permissions and status by group:

$ adb shell pm list permissions -d -g

Grant or revoke one or more permissions:

$ adb shell pm [grant|revoke] …

Permissions before 6.0 can be obtained after AndroidMenifest declaration, which will cause users to silently endure some unnecessary permissions, especially sensitive permissions such as address book and location SMS. After 6.0, we will only request permissions when we need them, and users can choose to refuse. The new mechanism better protects the user’s privacy. Google divides Normal Permissions into two categories. Normal Permissions generally do not involve user privacy and do not require user authorization, such as network access and Bluetooth (see appendix for detailed Permissions). Dangenpermission involves user privacy and requires user authorization. For example, read SDcard, start camera, access address book, etc., among which, the risk permissions are grouped. If the user has selected one of the risk permissions in this group before, there are mainly the following groups (see appendix for detailed permissions).

  1. Body sensor
  2. Calendar camera
  3. The address book
  4. The geographical position
  5. The microphone
  6. The phone
  7. SMS
  8. The storage space

2.2 Permission related apis

To make it easier for developers to manage permissions, Google provides the following four apis

The following three steps are required for common permission check

1. Check whether the permission is granted

//Activity.java
> public int checkSelfPermission(permission) 
Copy the code

This is used in the ContextCompat class to determine if the app has obtained a permission. If return to android. Content. PM. PackageManager# PERMISSION_GRANTED, explain the app has been granted permission, If return to android. Content. PM. PackageManager# PERMISSION_DENIED shows permissions have been banned

2. Apply for permission

//Activity.java public final void requestPermissions( new String[permission1,permission2,...] , requestCode)Copy the code

This is the method used to request permissions in the ActivityCompat and FragmentCompat classes

3, permissions, user callback after the system inside the popup window select the results through the Activity of the callback onRequestPermissionsResult method

Public void onRequestPermissionsResult (int requestCode, String [] permissions, int [] grantResults) {/ / continue execution logic or prompt access failure}Copy the code

These methods can be encapsulated in BaseActvity

This is used as a helper class

public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity, @nonNULL String Permission) this is used in the ActivityCompat and FragmentCompat classes to determine whether the permission query dialog is displayed. In the permission application process, if the user chooses to allow the permission to use or rejects the permission and checks the No more ask dialog box at the same time, the API will return false, indicating that the permission ask dialog box will not pop up, and the authorization popup does not support customization

The auxiliary function is very important, when dynamic permissions apply if the user if the user checked “no longer ask,” so the execution requestPermissions (after), onRequestPermissionsResult () will return PERMISSION_DENIED forever, We don’t want the application to never perform its original operation

When applying for permission for the first time, this function returns false by default. There is no need to inform the user of the reason for applying for permission. This function returns true when the first request is rejected, and the system Dialog will pop up with an option “Ask no more”. If the user checks this option, the function will always return false.

2.3 Adaptation

If the project’s targetSdkVersion < 23 is running on Android 6.0 or higher, the permissions requested in androidmanifest.xml will be granted by default. If a user manually reclaims permissions on the application permission page, the application will crash

Although the system reminds the user, it still depends on the user’s mood, so it is necessary to adapt the dynamic.

First of all, apps with a targetSdkVersion lower than 23 are granted all permissions by default, so if your previous APP had a targetSdkVersion lower than 23, it will still work. If the value is equal to or greater than 23, request Permission is required; otherwise, the system will crash and blink back. The following describes the steps for upgrading dynamic permissions

(1) Declare the target version SDK to modify the targetSdkVersion in build.gradle to be above 23

(2) Check the permission application place and request permission in the place where we need to use permission, check whether we have permission, such as read and write permission of external SD card, check whether we have permission before writing, if not, apply for permission

private void requestContactPermission() {
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS) ! = PackageManager. PERMISSION_GRANTED) {/ / application WRITE_CONTACTS permissions ActivityCompat. RequestPermissions (this, new String[]{Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_WRITE_CONTACTS); }}Copy the code

(3) Respond to user permission callback

The user can choose allow or deny, possibly deny. Callback onRequestPermissionsResult method, this method is similar to the onActivityResult. If it is a fragment, it is best to use the parent fragment, but not ActivityCompat. The getParentFragment().requestPermissions method is recommended.

(4) Conduct corresponding processing according to requestCode and grandResult (authorization result)

private void handleGrantResults(int requestCode, int[] grantResults) {
      if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) {
          if(grantResults [0] = = PackageManager. PERMISSION_GRANTED) {/ / Permission Granted access even executed after XXX}else{// Permission Denied Indicates the operation of xx. }}}Copy the code

3, the latter

3.1. How to handle permission Application if the user rejects it

If the user has rejected the core rights, apply again next time there will be no longer remind options, if you choose no longer remind, core rights not to get some function can’t use, you can choose to exit the application directly, or can be elegant, we check for yourself whether refused two times or more, you give a hint to the user do an interaction

private void handleContactPermission() {
        if (Integer.parseInt(Build.VERSION.SDK)>=23) {
            int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS);
            if(hasWriteContactsPermission ! = PackageManager.PERMISSION_GRANTED) {if(! shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) { showMessageOKCancel("You need to allow access to Contacts",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) { requestContactPermission(); // Apply for permission after confirmation. }});return; } requestContactPermission(); // If you don't have permission, apply. }}Copy the code

Or record users checked no longer ask Google provides a very good idea, see EasyPermissions. EasyPermissions does not store last shouldShowRequestPermissionRationale () returns a value, But after application permissions rejected calls shouldShowRequestPermissionRationale () method, if the returns false, indicating the user checked “no longer asked.”

Both methods can be used as reference methods.

3.2 Canceling Support for the Apache HTTP Client

Android version 6.0 removed support for the Apache HTTP client. If your application uses this client and is targeting Android 2.3 (API level 9) or higher, use the HttpURLConnection class instead. This API is more efficient because it reduces network usage through transparent compression and response caching and minimizes power consumption. To continue using the Apache HTTP API, you must first declare the following compile-time dependencies in the build.gradle file: Android {useLibrary ‘org.apache.http.legacy’}

3.3 Upgrade to 7.0 API 24 or above

For Android 7.0 oriented applications, StrictMode API policies enforced by the Android framework prohibit exposing the file:// URI outside of your application. If an intent that contains the URI of the file leaves your application, the application fails and a FileUriExposedException occurs. Common examples are accessing an upgrade downloaded to an internal SD card, accessing a phone album, and so on. There are many online solutions

The appendix

Normal Permissions

ACCESS_LOCATION_EXTRA_COMMANDS

ACCESS_NETWORK_STATE

ACCESS_NOTIFICATION_POLICY

ACCESS_WIFI_STATE

BLUETOOTH

BLUETOOTH_ADMIN

BROADCAST_STICKY

CHANGE_NETWORK_STATE

CHANGE_WIFI_MULTICAST_STATE

CHANGE_WIFI_STATE

DISABLE_KEYGUARD

EXPAND_STATUS_BAR

GET_PACKAGE_SIZE

INSTALL_SHORTCUT

INTERNET

KILL_BACKGROUND_PROCESSES

MODIFY_AUDIO_SETTINGS

NFC

READ_SYNC_SETTINGS

READ_SYNC_STATS

RECEIVE_BOOT_COMPLETED

REORDER_TASKS

REQUEST_INSTALL_PACKAGES

SET_ALARM

SET_TIME_ZONE

SET_WALLPAPER

SET_WALLPAPER_HINTS

TRANSMIT_IR

UNINSTALL_SHORTCUT

USE_FINGERPRINT

VIBRATE

WAKE_LOCK

WRITE_SYNC_SETTINGS

Dangenerous Permission

group:android.permission-group.CONTACTS permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS

group:android.permission-group.PHONE permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAIL

group:android.permission-group.CALENDAR permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA permission:android.permission.CAMERA

group:android.permission-group.SENSORS permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE permission:android.permission.RECORD_AUDIO

group:android.permission-group.SMS permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS

### Reference link

  • 1, source.android.com/source/buil…

  • 2, www.jianshu.com/p/06e55a322…

  • 3. Android 6.0 changes

  • 4. Runtime permissions

  • Permissions Best Practices

  • 6, Working with System Permissions

  • 7. Explore the detection and processing of Android 6.0 and above new permission system

  • 8. Android permission mechanism and adaptation experience

  • 9, Android 6.0 permission management, SDK >=23 request permission

    Welcome to pay attention to my public number, learn together, improve together ~Copy the code