Android 6.0 Runtime Rights Encapsulation (Avoid users choosing not to be prompted for permissions again)

For reprinting, please indicate the source: http://blog.csdn.net/donkor_/article/details/77326989

Preface:
In order to protect user privacy, Android 6.0 places applications for permissions when the application is running. For example, in previous development, developers only need to configure the required permissions in the manifest file. After installation, users can see in the application information in the settings: XX application to obtain ** permissions.User clicks to select the appropriate permissions for the application.Previous application rights users can choose to allow, alert, and deny.At the time of installation, the user already knows what permissions the application needs.However, there is a problem that users need a lot of privileges when installing applications (some developers ask for unnecessary privileges or all privileges to save time). At this time, users may not find some privilege requests that violate their privacy when installing applications, but only after installing, will they find that their privacy data is affected.Stealing.Actually, Android 6.0 dynamic rights are for the sake of users on the one hand, and Google is actually trying to avoid unnecessary lawsuits on the other.
There are already a lot of logic codes available online for Android 6.0 rights adaption.This is where the permission request is denied to the user and what to do if is not prompted.

Permission process:
_In Api 23, permissions need to be acquired dynamically and core permissions must be met.Standard process:

_However, there is a problem here, that is, in the system authorization pop-up link, the reminder box will have a check box that does not prompt anymore. If the user clicks no prompt anymore and refuses authorization, then the next authorization time, the system authorization pop-up window prompt box will not prompt, so it is necessary to customize the permission pop-up window prompt box, then the flow chart will become as follows.

Permission type:


_In the diagram, we can see that the whole permissions can be divided into system permissions and special permissions.System privileges are divided into normal and dangerous types.
normal: This permission type does not directly threaten the user's privacy, it can be registered directly in the manifest list, the system will help us to authorize by default.
dangerous: This gives app s direct access to user-sensitive data, not only by registering in the manifest list, but also by requesting authorization from the system when using it.
It is worth noting that there is a distinction between special privilege authorizations, SYSTEM_ALERT_WINDOW and WRITE_SETTINGS. Although these two privileges are also dangerous privilege types, the way these two authorization requests are made and other dangerous privileges require special handling.


Case description:
According to the official description, no "no prompt" option will be provided when the first permission request is made, but the permission request dialog box will only provide the option of "no prompt" if the user has previously rejected the permission request and initiated the permission request again. When the user has selected "no prompt" the permission request dialog box will not pop up again.Major mobile phone manufacturers'customization systems have made some changes to this logic, such as the Millet MIUI system "does not prompt" when the user first chooses to deny permission, the Huawei EMUI system will provide "do not prompt" option when the permission request pops up for the first time, and the Samsung part of the system always does not provide "do not prompt" option.
When the user chooses not to prompt, the developer needs to guide the user to set manual authorization for the page!
However, the android 6.0 system does not provide monitoring for the option of not prompting, so how do developers determine if users choose the option of not prompting?
The answer is through shouldShowRequestPermissionRationale().
The purpose of this method is to determine if you need to explain to the user why you need to request this privilege.
This method returns false when the first permission request is made.
This method returns true when the second permission request occurs.
This method returns false when the second permission request is made and the user chooses the option "Don't prompt again".From this logic, we can deduce that when a second permission request is rejected and shouldShowRequestPermissionRationale() returns false, the user must have chosen the option of not prompting again.

_Take RECORD_AUDIO, CAMERA, READ_EXTERNAL_STORAGE as examples.Full permission request succeeded, see your sister smash directly.Look at the picture below (). Without the picture, I would mumble

_When some permissions are restricted and the user does not select "Don't Prompt Again", pop up a dialog box to explain and request permissions

_When some permissions are restricted and the user checks "Don't Prompt Again", a dialog box pops up to guide the user to the Settings page for manual authorization

_Main code BaseActivity.java

package com.donkor.demo.permission;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {

    private final int mRequestCode = 1024;
    private RequestPermissionCallBack mRequestPermissionCallBack;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    /**
     * Permission Request Result Callback
     *
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        boolean hasAllGranted = true;
        StringBuilder permissionName = new StringBuilder();
        for (String s : permissions) {
            permissionName = permissionName.append(s + "\r\n");
        }
        switch (requestCode) {
            case mRequestCode: {
                for (int i = 0; i < grantResults.length; ++i) {
                    if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                        hasAllGranted = false;
                        //If shouldShowRequestPermissionRationale returns false if the user has refused authorization
                        // It can be inferred that the user selected the "Do not prompt" option, in which case the user needs to be guided to the Settings page for manual authorization
                        if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i])) {
                            new AlertDialog.Builder(BaseActivity.this).setTitle("PermissionTest")//Set Dialog Title
                                    .setMessage("[The user chooses not to prompt the button again, or the system defaults not to prompt (for example MIUI). " +
                                            "Guide users to the application settings page for manual authorization,Note prompting the user what permissions they need]" +
                                            "Failed to get related permissions:" + permissionName +
                                            "This will result in some features not working properly and will require manual authorization to the settings page")//Set what is displayed
                                    .setPositiveButton("De-authorization", new DialogInterface.OnClickListener() {//Add OK Button
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {//Determine the response event for the button
                                            //TODO Auto-generated method stub
                                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                            Uri uri = Uri.fromParts("package", getApplicationContext().getPackageName(), null);
                                            intent.setData(uri);
                                            startActivity(intent);
                                            dialog.dismiss();
                                        }
                                    }).setNegativeButton("cancel", new DialogInterface.OnClickListener() {//Add Return Button
                                @Override
                                public void onClick(DialogInterface dialog, int which) {//Response Events
                                    // TODO Auto-generated method stub
                                    dialog.dismiss();
                                }
                            }).setOnCancelListener(new DialogInterface.OnCancelListener() {
                                @Override
                                public void onCancel(DialogInterface dialog) {
                                    mRequestPermissionCallBack.denied();
                                }
                            }).show();//Show this dialog in key response events
                        } else {
                            //User rejects permission request, but no "Don't prompt again" option is selected
                            mRequestPermissionCallBack.denied();
                        }
                        break;
                    }
                }
                if (hasAllGranted) {
                    mRequestPermissionCallBack.granted();
                }
            }
        }
    }

    /**
     * Initiate Permission Request
     *
     * @param context
     * @param permissions
     * @param callback
     */
    public void requestPermissions(final Context context, final String[] permissions,
                                   RequestPermissionCallBack callback) {
        this.mRequestPermissionCallBack = callback;
        StringBuilder permissionNames = new StringBuilder();
        for (String s : permissions) {
            permissionNames = permissionNames.append(s + "\r\n");
        }
        //If all permissions are authorized, the direct return authorization succeeds, and if one is not authorized, a permission request is initiated
        boolean isAllGranted = true;
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) {
                isAllGranted = false;
                if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, permission)) {
                    new AlertDialog.Builder(BaseActivity.this).setTitle("PermissionTest")//Set Dialog Title
                            .setMessage("[Users have rejected your request, so explain it when you make it)" +
                                    "Hello, you need the following permissions:" + permissionNames +
                                    " Please allow, otherwise it will affect the normal use of some functions.")//Set what is displayed
                            .setPositiveButton("Determine", new DialogInterface.OnClickListener() {//Add OK Button
                                @Override
                                public void onClick(DialogInterface dialog, int which) {//Determine the response event for the button
                                    //TODO Auto-generated method stub
                                    ActivityCompat.requestPermissions(((Activity) context), permissions, mRequestCode);
                                }
                            }).show();//Show this dialog in key response events
                } else {
                    ActivityCompat.requestPermissions(((Activity) context), permissions, mRequestCode);
                }
                break;
            }
        }
        if (isAllGranted) {
            mRequestPermissionCallBack.granted();
            return;
        }
    }

    /**
     * Permission Request Result Callback Interface
     */
    interface RequestPermissionCallBack {
        /**
         * Consent to authorization
         */
        void granted();

        /**
         * Revoke Authorization
         */
        void denied();
    }
}

_Button Request Permission Primary Code in SplashActivity.java

requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.CAMERA,
                        Manifest.permission.READ_EXTERNAL_STORAGE},
                new RequestPermissionCallBack() {
                    @Override
                    public void granted() {
                        Toast.makeText(SplashActivity.this, "Permission acquired successfully, proceed to next step", Toast.LENGTH_SHORT).show();
                        Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                        startActivity(intent);
                        SplashActivity.this.finish();
                    }

                    @Override
                    public void denied() {
                        Toast.makeText(SplashActivity.this, "Access to some permissions failed and normal functionality was affected,2 Automatically exit after seconds", Toast.LENGTH_LONG).show();
                        //Automatically exit after 2 seconds
                        mHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                SplashActivity.this.finish();
                            }
                        }, 2000);
                    }
                });

Materials and References:
http://www.cnblogs.com/cr330326/p/5181283.html
http://blog.csdn.net/caroline_wendy/article/details/50587230

Mei Chuan Photos and Source Download Address: http://download.csdn.net/download/donkor_/9938151

Keywords: Android MIUI Java Google

Added by cschotch on Mon, 03 Jun 2019 20:28:04 +0300