Android Rights Management and Dynamic Request Permissions

Android Rights Management

1. Basic Introduction

_Android security architecture states that by default, no application has the right to perform any action that adversely affects other applications, operating systems or users. This includes reading and writing the user's private data, such as contacts or e-mail, reading and writing files from other applications, performing network access, keeping the device awake, and so on.
_Application privileges are based on system security features and help Android support the following goals related to user privacy:

  • Control: Users can control the data they share with the app.
  • Transparency: Users can see what data is used by the application and why the application accesses the data.
  • Data Minimization: Applications can only access and use the data required for a specific task or operation invoked by the user.

Permission Type

Android divides permissions into different types, including install-time permissions, run-time permissions, and special permissions. Each permission type indicates the limited range of data that the application can access and the limited range of operations that the application can perform when the system grants the permission to apply.

1. Installation Permissions

_Installation-time privileges grant the application restricted access to restricted data and allow the application to perform restricted operations that have minimal impact on the system or other applications. If install-time permissions are declared in an application, they are automatically granted when the user allows the application to install.
_Installation rights are divided into several subtypes, including common rights and signature rights.

  • General permissions
    Such permissions allow access to data beyond the application sandbox and perform operations beyond the application sandbox. However, these data and operations pose little risk to user privacy and operations on other applications. The system assigns a "normal" level of protection to common privileges.

  • Signature rights
    When an application declares the signing rights defined by another application, if two applications sign with the same signing file, the system grants that right to the other application at installation time. Otherwise, the system cannot grant the privilege to the former. Signature rights are assigned a "signature" protection level.

2. Runtime permissions

_Runtime privileges, also known as dangerous privileges, grant an application additional access to restricted data and allow the application to perform restricted operations that have more severe impact on the system and other applications. You need to request permissions at runtime before you can access restricted data or perform restricted operations. When the application requests runtime permissions, a pop-up box displays the runtime permission request prompt. Many runtime privileges access user private data, which is a special kind of restricted data that contains potentially sensitive information. For example, location information and contact information belong to the user's private data. Runtime privileges are assigned a "dangerous" protection level.
_Runtime privilege mechanism is a new feature of Android 6.0 (M), so different Android versions of devices and targetSdkVersion settings can affect the performance of applications applying for dangerous privileges.

  • In Android6. When used on devices prior to version 0, applications will apply for old permission systems, hazardous permissions, or installations of applications, regardless of whether the targetSdkVersion is greater than 23.
  • In Android6. The targetSdkVersion set in the application will be used to determine when the device version 0 or higher is used: 1) If the targetSdkVersion is lower than 23, the old rules will continue to be used and hazardous rights will be applied for at installation time; 2) If the targetSdkVersion is greater than or equal to 23, the application needs to apply for permission dynamically at runtime.

Note: Starting with Android 6.0 (Marshmallow, API 23), users can revoke a privilege for an application at any time, even if the targetSdkVersion applied is less than 23. Therefore, you must ensure that the application performs well after requesting permissions fails.


_If the device is running Android 6.0 or higher and the targetSdkVersion applied is 23 or higher, the system will behave as follows when the user requests dangerous permissions:

  • If an application requests a dangerous permission that is already listed in its manifest file and the application does not currently have any permissions for that permission group, a dialog box is displayed to the user asking if the user is authorized, which describes the permission group the application wants to access instead of the specific permissions within the group. For example, if an application requests READ_CONTACTS privilege, the system will pop up a dialog box to inform the user that the application needs to access the device's contacts, if the user allows authorization, then the system will grant the application the required privileges.
  • If an application requests a dangerous permission that is already listed in its manifest file, and the application currently has other dangerous permissions for that permission group, the system grants that permission immediately without notifying the user. For example, if an application has been previously requested and granted READ_CONTACTS permission, then it requests WRITE_ This privilege will be granted immediately upon CONTACTS.

Permission group concept:
_Permissions are grouped according to the functions and features of the device. The system handles permission requests in the form of permission groups, which may correspond to several permissions requested in Manifest. For example, the STORAGE permission group includes READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions. The privilege group approach makes it easier for users to understand privileges and handle APP privilege requests, preventing too many complex privileges from being granted individually.
_Any privilege can belong to a privilege group, including normal privileges and application customized privileges. However, permission groups only affect the user experience when permissions are dangerous. Permission groups with normal permissions can be ignored.

Hazardous permissions and corresponding groupings are as follows:

3. Special privileges

_Special privileges correspond to specific application operations. Only platform and original equipment manufacturer (OEM) can define special permissions. In addition, if platforms and OEMs want to prevent someone from performing particularly powerful operations, such as drawing through other applications, special privileges are usually defined. Special privileges are assigned an "appop" protection level. After Android 6.0, only system applications will be able to use these special privileges.




2. Dynamic Permission Application

1. Main usage methods

(1)ContextCompat.checkSelfPermission
_Check if the application has a dangerous permission, and if the application has this permission, the method will return to PackageManager.PERMISSION_GRANTED; If the application does not have this permission, the method will return to PackageManager.PERMISSION_DENIED.

(2)ActivityCompat.requestPermissions
_The application can dynamically apply for permissions through this method, after which a dialog box prompts the user to authorize the group of permissions requested.

(3)ActivityCompat.shouldShowRequestPermissionRationale
_Check if this permission was last denied. This method returns true if the permission was previously requested and the user rejected the request, but the request can continue. The following returns false:1) Users have never applied for this privilege; 2) In the past, the user rejected the permission request and chose the Don't ask again option in the permission request system dialog box; 3) The user has allowed the request for this privilege; 4) The device specification prohibits the application of this authority.
_Therefore, it is useless to use this method alone and should be used in the callback for requesting permission.

Note: There may be differences in the handling of rights between different mobile phone systems. Some mobile phone systems default to no more pop-up if they choose to reject the authorization request when popping up, and then call this method to return false.

(4)onRequestPermissionsResult
_When permission is requested, a dialog box is displayed to the user. When the user responds, the system calls the applied onRequestPermissionsResult() method, passes the user response to it, and processes the corresponding scenario.

2. Call process

(1) In Android Manifest. The permissions to be applied for are stated in the xml.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>

(2) Check the permissions before applying for permissions, and apply for permissions if the application does not have such permissions; If you apply for more than one privilege at a time, you should check the privileges one by one, and finally apply for unauthorized privileges in a unified way.

private String PM_SINGLE=Manifest.permission.WRITE_EXTERNAL_STORAGE;
//Request Single Permission
public void applyForSinglePermission(){
    Log.i(TAG,"applyForSinglePermission");
    try{
        //If the operating system SDK level is above 23 (android6.0), make a dynamic permission request
        if(Build.VERSION.SDK_INT>=23){
			//Determine whether you have permissions
            int nRet=ContextCompat.checkSelfPermission(this,PM_SINGLE);
            Log.i(TAG,"checkSelfPermission nRet="+nRet);
            if(nRet!= PackageManager.PERMISSION_GRANTED){
                Log.i(TAG,"Perform Permission Request...");
                ActivityCompat.requestPermissions(this,new String[]{PM_SINGLE},10000);
            }
            else{
                showToast("Permissions authorized");
            }
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}

private String[] PM_MULTIPLE={
	Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.CAMERA,Manifest.permission.WRITE_CONTACTS
};
//Request Multiple Permissions
public void applyForMultiplePermissions(){
    Log.i(TAG,"applyForMultiplePermissions");
    try{
        //If the operating system SDK level is above 23 (android6.0), make a dynamic permission request
        if(Build.VERSION.SDK_INT>=23){
            ArrayList<String> pmList=new ArrayList<>();
            //Get the current list of unauthorized permissions
            for(String permission:PM_MULTIPLE){
                int nRet=ContextCompat.checkSelfPermission(this,permission);
                Log.i(TAG,"checkSelfPermission nRet="+nRet);
                if(nRet!= PackageManager.PERMISSION_GRANTED){
                    pmList.add(permission);
                }
            }

            if(pmList.size()>0){
                Log.i(TAG,"Perform Permission Request...");
                String[] sList=pmList.toArray(new String[0]);
                ActivityCompat.requestPermissions(this,sList,10000);
            }
            else{
                showToast("All permissions are authorized");
            }
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}

(3) Override the onRequestPermissionsResult callback method to listen for user authorization operations.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    try{
        ArrayList<String> requestList=new ArrayList<>();//Allow Question List
        ArrayList<String> banList=new ArrayList<>();//Prohibited List
        for(int i=0;i<permissions.length;i++){
            if(grantResults[i] == PackageManager.PERMISSION_GRANTED){
                Log.i(TAG,"["+permissions[i]+"]Permission authorization succeeded");
            }
            else{
				//Determine whether to allow reapplication of this privilege
                boolean nRet=ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[i]);
                Log.i(TAG,"shouldShowRequestPermissionRationale nRet="+nRet);
                if(nRet){//Allow re-application
                    requestList.add(permissions[i]);
                }
                else{//Prohibit applications
                    banList.add(permissions[i]);
                }
            }
        }

        //Prioritize the prohibition list
        if(banList.size()>0){//Inform the role of the privilege and require that the privilege be granted manually
            showFinishedDialog();
        }
        else if(requestList.size()>0){//Inform about the role of permissions and reapply
            showTipDialog(requestList);
        }
        else{
            showToast("Permission authorization succeeded");
        }
    }catch (Exception e){
        e.printStackTrace();
        showToast("Exception occurred in permission request callback");
    }
}

public void showFinishedDialog(){
    AlertDialog dialog = new AlertDialog.Builder(this)
            .setTitle("warning")
            .setMessage("Please go to Settings to open the relevant permissions, otherwise the function will not work properly!")
            .setPositiveButton("Determine", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // In general, if the user does not authorize, the function will not run, do exit processing
                    finish();
                }
            })
            .create();
    dialog.show();
}

public void showTipDialog(ArrayList<String> pmList){
    AlertDialog dialog = new AlertDialog.Builder(this)
            .setTitle("Tips")
            .setMessage("["+pmList.toString()+"]Permissions are necessary to apply permissions, please authorize")
            .setPositiveButton("Determine", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    String[] sList=pmList.toArray(new String[0]);
                    //Re-apply for this permission
                    ActivityCompat.requestPermissions(MainActivity.this,sList,10000);
                }
            })
            .create();
    dialog.show();
}



3. PermissionUtil Tool Class

_This class is a Self-encapsulated tool class for Android privilege requests. It can apply for multiple privileges by privilege group name or privilege name, and encapsulate the processing logic for user authorization operation. It can define different response processing for user authorization by passing in callback interface.

PermissionUtil implementation:

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * author:chenjs
 */
public class PermissionUtil {
	private static final String TAG=PermissionUtil.class.getSimpleName();
	private static final boolean LOG_FLAG=true;//Log Identification

	//calendar
	private static final String[] Group_Calendar={
	        Manifest.permission.READ_CALENDAR,Manifest.permission.WRITE_CALENDAR
	};
	//Camera
	private static final String[] Group_Camera={
	        Manifest.permission.CAMERA
	};
	//Mail list
	private static final String[] Group_Contacts={
	        Manifest.permission.WRITE_CONTACTS,Manifest.permission.GET_ACCOUNTS,
	        Manifest.permission.READ_CONTACTS
	};
	//Location
	private static final String[] Group_Location={
	        Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION
	};
	//Microphone
	private static final String[] Group_Microphone={
	        Manifest.permission.RECORD_AUDIO
	};
	//Telephone
	private static final String[] Group_Phone={
	        Manifest.permission.READ_PHONE_STATE,Manifest.permission.CALL_PHONE,
	        Manifest.permission.READ_CALL_LOG,Manifest.permission.WRITE_CALL_LOG,
	        Manifest.permission.ADD_VOICEMAIL,Manifest.permission.USE_SIP,
	        Manifest.permission.PROCESS_OUTGOING_CALLS
	};
	//sensor
	private static final String[] Group_Sensors={
	        Manifest.permission.BODY_SENSORS
	};
	//Short message
	private static final String[] Group_Sms={
	        Manifest.permission.READ_SMS,Manifest.permission.SEND_SMS,
	        Manifest.permission.RECEIVE_SMS,Manifest.permission.RECEIVE_MMS,
	        Manifest.permission.RECEIVE_WAP_PUSH
	};
	//storage
	private static final String[] Group_Storage={
	        Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE
	};
	private static Map<String,String[]> m_PermissionGroupList=null;
	static{
	    initMap();
	}

	/**
	 * Apply for a set of privileges through the privilege group name
	 * @param context
	 * @param permissionGroupName
	 * @param requestCode
	 * @param listener
	 */
	public static void requestByGroupName(Activity context, String permissionGroupName,int 	requestCode,OnPermissionsListener listener){
	    requestByGroupName(context, new String[]{permissionGroupName}, requestCode, listener);
	}

	/**
	 * Request multiple groups of permissions by permission group name
	 * @param context Activity context
	 * @param pgNameArray Multiple Rights Group Names to Request
	 * @param requestCode Request Code
	 * @param listener Callback interface
	 */
	public static void requestByGroupName(Activity context, String[] pgNameArray,int 	requestCode,OnPermissionsListener listener){
	    showLog("requestByPermissionGroup");
	    try{
	        //If the operating system SDK level is above 23 (android6.0), make a dynamic permission request
	        if(Build.VERSION.SDK_INT>=23 && pgNameArray!=null){
	            String[] permissionsList=getAppPermissionsList(context);//Apply Permission List
	            ArrayList<String> targetList=new ArrayList<>();
	            if(permissionsList==null || permissionsList.length==0){
	                showLog("Access list is empty");
	                return;
	            }

	            for(String groupName:pgNameArray){
	                ArrayList<String> tmpPermissionList=isPermissionDeclared(permissionsList,groupName);
	                if(tmpPermissionList==null){//not found
	                    showLog("not found["+groupName+"]Permissions in");
	                    continue;
	                }

	                for(int i=0;i<tmpPermissionList.size();i++){
	                    //Determine whether you have permissions
	                    int nRet=ContextCompat.checkSelfPermission(context,tmpPermissionList.get(i));
	                    if(nRet!= PackageManager.PERMISSION_GRANTED){
	                        targetList.add(tmpPermissionList.get(i));
	                    }
	                }
	            }

	            if(targetList.size()>0){
	                showLog("Make the following permission request:"+targetList.toString());
	                String[] sList=targetList.toArray(new String[0]);
	                ActivityCompat.requestPermissions(context,sList,requestCode);
	            }
	            else{
	                showLog("All permissions are authorized");
	                if(listener!=null){
	                    listener.onPermissionsOwned();
	                }
	            }
	        }
	    }catch(Exception e){
	        e.printStackTrace();
	    }
	}

	/**
	 * Request a set of permissions by permission name
	 * @param context
	 * @param permission
	 * @param requestCode
	 * @param listener
	 */
	public static void requestByPermissionName(Activity context, String permission,int 	requestCode,OnPermissionsListener listener){
	    requestByPermissionName(context, new String[]{permission}, requestCode, listener);
	}

	/**
	 * Request multiple groups of permissions by permission name
	 * @param context Activity context
	 * @param permissionArray Multiple Rights Names to Request
	 * @param requestCode Request Code
	 * @param listener Callback interface
	 */
	public static void requestByPermissionName(Activity context, String[] permissionArray,int 	requestCode,OnPermissionsListener listener){
	    showLog("requestPermissions");
	    try{
	        //If the operating system SDK level is above 23 (android6.0), make a dynamic permission request
	        if(Build.VERSION.SDK_INT>=23 && permissionArray!=null){
	            ArrayList<String> targetList=new ArrayList<>();
	            for(String strPermission:permissionArray){
	                //Determine whether you have permissions
	                int nRet=ContextCompat.checkSelfPermission(context,strPermission);
	                if(nRet!= PackageManager.PERMISSION_GRANTED){
	                    targetList.add(strPermission);
	                }
	            }

	            if(targetList.size()>0){
	                showLog("Make the following permission request:"+targetList.toString());
	                String[] sList=targetList.toArray(new String[0]);
	                ActivityCompat.requestPermissions(context,sList,requestCode);
	            }
	            else{
	                showLog("All permissions are authorized");
	                if(listener!=null){
	                    listener.onPermissionsOwned();
	                }
	            }
	        }
	    }catch(Exception e){
	        e.printStackTrace();
	    }
	}

	/**
	 * Handle user actions when requesting permissions
	 * @param context
	 * @param permissions Permission to apply
	 * @param grantResults Authorization Status of Permissions
	 * @param listener Callback interface
	 * @param controlFlag A control identifier that determines whether to continue processing the list of re-requests after responding to the list of prohibitions (to avoid conflicting processing both prohibit and re-apply lists, such as popping up two prompt boxes)
	 */
	public static void onRequestPermissionsResult(Activity context,String[] permissions, int[] 	grantResults,OnPermissionsListener listener,boolean controlFlag) {
	    try{
	        ArrayList<String> requestList=new ArrayList<>();//Re-application List
	        ArrayList<String> banList=new ArrayList<>();//Prohibited List
	        for(int i=0;i<permissions.length;i++){
	            if(grantResults[i] == PackageManager.PERMISSION_GRANTED){
	                showLog("["+permissions[i]+"]Permission authorization succeeded");
	            }
	            else{
	                boolean nRet=ActivityCompat.shouldShowRequestPermissionRationale(context,permissions[i]);
	                //Log.i(TAG,"shouldShowRequestPermissionRationale nRet="+nRet);
	                if(nRet){//Allow re-application
	                    requestList.add(permissions[i]);
	                }
	                else{//Prohibit applications
	                    banList.add(permissions[i]);
	                }
	            }
	        }

	        do{
	            //Prioritize the prohibition list
	            if(banList.size()>0){
	                if(listener!=null){
	                    listener.onPermissionsForbidden(permissions,grantResults,banList);
	                }
	                if(!controlFlag){//Skip processing the reapplieable list if the control is identified as false after processing the prohibited list
	                    break;
	                }
	            }
	            if(requestList.size()>0){
	                if(listener!=null){
	                    listener.onPermissionsDenied(permissions,grantResults,requestList);
	                }
	            }
	            if(banList.size()==0 && requestList.size()==0){
	                showLog("Permission authorization succeeded");
	                if(listener!=null){
	                    listener.onPermissionsSucceed();
	                }
	            }
	        }while (false);
	    }catch (Exception e){
	        e.printStackTrace();
	    }
	}

	/**
	 * Judging permission status
	 * @param context
	 * @param permission Permission Name
	 * @return
	 */
	public static boolean checkPermission(Context context,String permission){
	    try{
	        //If the operating system SDK level is above 23 (android6.0), make a dynamic permission request
	        if(Build.VERSION.SDK_INT>=23){
	            int nRet= ContextCompat.checkSelfPermission(context,permission);
	            showLog("checkSelfPermission nRet="+nRet);

	            return nRet==PackageManager.PERMISSION_GRANTED? true : false;
	        }
	        return true;
	    }catch(Exception e){
	        e.printStackTrace();
	        return false;
	    }
	}

	/**
	 * Get the list of permissions in the current application manifest
	 * @param context Application Context
	 * @return
	 */
	public static String[] getAppPermissionsList(Context context){
	    try{
	        PackageManager packageManager = context.getApplicationContext().getPackageManager();
	        String packageName=context.getApplicationContext().getPackageName();
	        String[] array = packageManager.getPackageInfo(packageName,PackageManager.GET_PERMISSIONS).requestedPermissions;
	        return array;
	    }catch (Exception e){
	        e.printStackTrace();
	    }
	    return null;
	}

	/**
	 * Determines whether permissions in the specified permission group are declared in the permission list
	 * @param permissionList Permission List
	 * @param permissionGroup Permission Group Name
	 * @return Returns found permission group permissions if present, otherwise returns null
	 */
	public static ArrayList<String> isPermissionDeclared(String[] permissionList, String permissionGroup){
	    try{
	        if(permissionList!=null && permissionGroup!=null){
	            String[] pmGroup=m_PermissionGroupList.get(permissionGroup);
	            if(pmGroup!=null){
	                ArrayList<String> arrayList=new ArrayList<>();
	                //ergodic
	                for(int i=0;i<pmGroup.length;i++){
	                    String strPermission=pmGroup[i];
	                    for(int j=0;j< permissionList.length;j++){
	                        if(strPermission.equals(permissionList[j])){//Find permissions in the specified permission group
	                            arrayList.add(strPermission);
	                            break;
	                        }
	                    }
	                }
	                if(arrayList.size()==0){
	                    return null;
	                }
	                return arrayList;
	            }
	        }
	    }catch (Exception e){
	        e.printStackTrace();
	    }
	    return null;
	}

	private static void initMap(){
	    if(m_PermissionGroupList==null){
	        m_PermissionGroupList=new HashMap<>();
	        m_PermissionGroupList.put(Manifest.permission_group.CALENDAR,Group_Calendar);
	        m_PermissionGroupList.put(Manifest.permission_group.CAMERA,Group_Camera);
	        m_PermissionGroupList.put(Manifest.permission_group.CONTACTS,Group_Contacts);
	        m_PermissionGroupList.put(Manifest.permission_group.LOCATION,Group_Location);
	        m_PermissionGroupList.put(Manifest.permission_group.MICROPHONE,Group_Microphone);
	        m_PermissionGroupList.put(Manifest.permission_group.PHONE,Group_Phone);
	        m_PermissionGroupList.put(Manifest.permission_group.SENSORS,Group_Sensors);
	        m_PermissionGroupList.put(Manifest.permission_group.SMS,Group_Sms);
	        m_PermissionGroupList.put(Manifest.permission_group.STORAGE,Group_Storage);
	    }
	}

	private static void showLog(String str){
	    if(LOG_FLAG){
	        Log.i(TAG,str);
	    }
	}

	public interface OnPermissionsListener {
	    /**
	     * Processing when permissions are already in place
	     */
	    void onPermissionsOwned();
	    /**
	     * Handling when permissions are prohibited
	     * @param permissions Full permissions requested
	     * @param grantResults Authorization Status of Permissions
	     * @param pmList List of permissions prohibited from applying
	     */
	    void onPermissionsForbidden(String[] permissions, int[] grantResults,ArrayList<String> pmList);
	    /**
	     * Processing when permission is denied
	     * @param permissions
	     * @param grantResults
	     * @param pmList List of rights that can be re-applied
	     */
	    void onPermissionsDenied(String[] permissions, int[] grantResults,ArrayList<String> pmList);
	    /**
	     * Processing when permission request succeeds
	     */
	    void onPermissionsSucceed();
	}
}	

The following examples can be used:

private final int RequestCode3_1 =10004;
//Rewrite by user according to their needs
private PermissionUtil.OnPermissionsListener mListener3_1=new PermissionUtil.OnPermissionsListener() {
    @Override
    public void onPermissionsOwned() {
        showTip("This privilege already exists");
    }

    @Override
    public void onPermissionsForbidden(String[] permissions, int[] grantResults, ArrayList<String> pmList) {
        showTip("The following permissions are prohibited:"+pmList.toString());
        AlertDialog dialog = new AlertDialog.Builder(mContext)
                .setTitle("warning")
                .setMessage("Go to Settings and turn it on manually"+pmList.toString()+"Jurisdiction!")
                .setPositiveButton("Determine", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                })
                .create();
        dialog.show();
    }

    @Override
    public void onPermissionsDenied(String[] permissions, int[] grantResults, ArrayList<String> pmList) {
        showTip("The following permissions were denied authorization:"+pmList.toString());
        //Re-request permissions
        AlertDialog dialog = new AlertDialog.Builder(mContext)
                .setTitle("Tips")
                .setMessage("["+pmList.toString()+"]Permissions are necessary to apply permissions, please authorize")
                .setPositiveButton("Determine", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String[] sList=pmList.toArray(new String[0]);
                        //Re-apply for permissions and apply for multiple groups of permissions by permission name
                        PermissionUtil.requestByPermissionName(mContext,sList, RequestCode3_1,mListener3_1);
                    }
                })
                .create();
        dialog.show();
    }

    @Override
    public void onPermissionsSucceed() {
        showTip("Permission application succeeded");
    }
};

public void requestPermission3_1(){
    String[] pgArray=new String[]{
            Manifest.permission_group.SENSORS,Manifest.permission_group.SMS,Manifest.permission_group.STORAGE
    };
    showTip("Conduct[sensor+Short message+storage]Permission Request...");
	//Apply for specified permissions by permission group name
    PermissionUtil.requestByGroupName(mContext,pgArray, RequestCode3_1,mListener3_1);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){//It can be handled differently for different privilege request operations or in the same way (requestCode is not judged)
        case RequestCode3_1:{
            PermissionUtil.onRequestPermissionsResult(mContext,permissions,grantResults,mListener3_1,false);
            break;
        }
    }
}

Specific tool classes and demonstration projects are placed on Github, which interested students can learn about. If you have any questions, please come to discuss them and make progress together.

GitHub address: https://github.com/JINSHENGCCC/Android_Common/tree/master/AndroidPermission/src




4. Reference

  1. Permissions in Android
  2. Seconds to understand Android development rights summary
  3. Android Rights Management Details
  4. Android Runtime Rights Processing
  5. Android 6.0 Dynamic Permission Request
  6. Android6.0 Hazardous Rights List

Keywords: Android

Added by nabeelkhan on Fri, 21 Jan 2022 11:19:03 +0200