Android permissions official document

The article directories

  • Common permissions and dangerous permissions
  • To apply for permission
    • Chestnut 1 Contact rights
    • Kotlin implements making calls
  • Try to encapsulate yourself
    • Step by step on
    • The complete MPermissionsActivity code
    • usage
  • Third party library permission library use
    • Guo permissionX of god
    • EasyPermission

Common permissions and dangerous permissions

If your application lists common permissions (permissions that do not pose significant risks to user privacy or device operations), the system automatically grants these permissions to the application. For example, the permission to set the time zone is common

If your application lists hazardous permissions (that is, permissions that may affect user privacy or proper device operation), such as SEND_SMS permissions, the user must explicitly consent to grant these permissions. How Android requests a user to grant dangerous permissions depends on the version of Android on the user’s device and the target system version of the application. If the device is running Android 6.0 (API level 23) or higher, and the application’s targetSdkVersion is 23 or higher, the application must request hazardous permissions from the user at runtime

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_SETTINGSCopy the code

Dangerous Permissions

Looking at dangerous Permissions above, there is a problem as if the dangerous permissions are grouped together

If the app is running on an Android 6.x machine, this is true for the authorization mechanism. If you apply for a dangerous permission, assuming that your app has already been granted the same set of dangerous permissions by the user, the system will grant it immediately, without the user having to click permission. For example, if your app is already authorized for READ_CONTACTS, when your app applies for WRITE_CONTACTS, it will be authorized directly

In addition, the text description above the dialog that pops up at request is also a description of the entire permission group, not a single permission.

However, it is important not to rely too much on the permission group. Apply for every dangerous permission as normal as possible, because this permission group may change in the later version

To apply for permission

Chestnut 1 Contact rights

1. Add the required permissions to the AndroidManifest file

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
Copy the code

2. Checking Permissions If your application requires a hazardous permission, you must check that you have it every time you perform an operation that requires it. In Android 6.0 (API level 23) and later, users can revoke dangerous permissions from any application at any time. Do not check or request permissions when a user opens your application, but wait until the user selects or enables features that require specific permissions

if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
            // The user has the permission
            Toast.makeText(this."Have access",Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this."No permissions",Toast.LENGTH_SHORT).show();
        }
Copy the code

ContextCompat. CheckSelfPermission (), is mainly used to detect a certain whether permission has been granted, Method returns the value for the PackageManager. PERMISSION_DENIED or PackageManager. PERMISSION_GRANTED. When DENIED is returned, you need to apply for authorization

3. Request user approval for each permission at run time

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
	requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_CODE);
}
Copy the code

4. Handle permission application callback

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                            int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE:
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 &&
                        grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                   // Permission granted, continue operation
                    Toast.makeText(this."Have access", Toast.LENGTH_SHORT).show();
                }  else {
                    // Explain to the user that some functions will be unavailable if the permission is denied
                    Toast.makeText(this."If this permission is denied, some functions will become unavailable.", Toast.LENGTH_SHORT).show();
                }
                return; }}Copy the code

For the result of the request for permissions, first verify that requestCode locates your request, then verify that grantResults corresponds to the result of the request, where the array corresponds to the second permission string array at the time of the request. If you apply for two permissions at the same time, then the length of grantResults is 2, and the results of your two permissions are recorded separately. If the application is successful, you can do your work

If you keep saying no



If permission is allowed

Kotlin implements making calls

Apply for permissions in AndroidManifest

 <uses-permission android:name="android.permission.CALL_PHONE"/>
Copy the code

If you run the call() method directly, it crashes with a message saying Permission Denied, because on Android 6.0 and above you must run time Permission processing when using dangerous permissions

class TestActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
        btn.setOnClickListener {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) ! = PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), 1)}else {
                call()
            }
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode){
            1 -> if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                call()
            }else{
                Toast.makeText(this."You denied the permission",Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun call(a) {
        try {
            val intent = Intent(Intent.ACTION_CALL)
            intent.data = Uri.parse("tel:10086")
            startActivity(intent)
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }
}
Copy the code

Try to encapsulate yourself

Let’s take a closer look at permission handling by trying encapsulation ourselves

Step by step on

Let’s try encapsulation to reduce a lot of rework. Encapsulating an MPermissionsActivity is as follows

	/** * Check whether all permissions are authorized **@param permissions
     * @return* /
    private boolean checkPermissions(String[] permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }

        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) ! = PackageManager.PERMISSION_GRANTED) {return false; }}return true;
    }
Copy the code

2. Obtain the list of permissions to be applied for in the permission set

	/** * Get the list of permissions to apply for in the permission set **@param permissions
     * @return* /
    private List<String> getDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissionList = new ArrayList<>();
        for (String permission : permissions) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (ContextCompat.checkSelfPermission(this, permission) ! = PackageManager.PERMISSION_GRANTED || shouldShowRequestPermissionRationale(permission)) { needRequestPermissionList.add(permission); }}}return needRequestPermissionList;
    }
Copy the code

3. Request permission

/** * Request permission **@paramPermissions Permissions *@paramRequestCode specifies the requestCode for requesting permission */
    public void requestPermission(String[] permissions, int requestCode) {
        this.REQUEST_CODE_PERMISSION = requestCode;
        if (checkPermissions(permissions)) {
            permissionSuccess(REQUEST_CODE_PERMISSION);
        } else {
            List<String> needPermissions = getDeniedPermissions(permissions);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(needPermissions.toArray(newString[needPermissions.size()]), REQUEST_CODE_PERMISSION); }}}Copy the code

4. Handle permission request callback

  /** * System requests permission callback **@param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSION) {
            if (verifyPermissions(grantResults)) {
                permissionSuccess(REQUEST_CODE_PERMISSION);
            } else{ permissionFail(REQUEST_CODE_PERMISSION); showTipsDialog(); }}}Copy the code

5. Check whether the processing permission request callback user is authorized

/** * Verify that all permissions are granted **@param grantResults
     * @return* /
    private boolean verifyPermissions(int[] grantResults) {
        for (int grantResult : grantResults) {
            if(grantResult ! = PackageManager.PERMISSION_GRANTED) {return false; }}return true;
    }
Copy the code

Authorization success handler function

/** * Permission obtained successfully **@param requestCode
     */
    public void permissionSuccess(int requestCode) {
        Log.d(TAG, "Permission obtained successfully =" + requestCode);
    }
Copy the code

7. Authorization failure processing function and pop-up user prompt

/** * Failed to obtain permission *@param requestCode
     */
    public void permissionFail(int requestCode) {
        Log.d(TAG, "Permission failed =" + requestCode);
    }

  /** * Displays a prompt dialog box */
    private void showTipsDialog(a) {
        new AlertDialog.Builder(this)
                .setTitle("Warning message")
                .setMessage("The current application does not have the necessary permissions, so this function is temporarily unavailable. If necessary, please click the "OK" button to go to the setting center for permission authorization.)
                .setNegativeButton("Cancel", (dialog, which) -> {
                })
                .setPositiveButton("Sure", (dialog, which) -> startAppSettings()).show();
    }
Copy the code

8. After the user is prompted for authorization failure, he wants to open the page of setting APP permissions again

  /** * Launches the current app Settings page */
    private void startAppSettings(a) {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }
Copy the code

The complete MPermissionsActivity code

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import java.util.ArrayList;
import java.util.List;

public class MPermissionsActivity extends AppCompatActivity {
    private final String TAG = "MPermissions";
    private int REQUEST_CODE_PERMISSION = 0x00099;

    /** * Check whether all permissions are authorized **@param permissions
     * @return* /
    private boolean checkPermissions(String[] permissions) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }

        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) ! = PackageManager.PERMISSION_GRANTED) {return false; }}return true;
    }

    /** * Get the list of permissions to apply for in the permission set **@param permissions
     * @return* /
    private List<String> getDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissionList = new ArrayList<>();
        for (String permission : permissions) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (ContextCompat.checkSelfPermission(this, permission) ! = PackageManager.PERMISSION_GRANTED || shouldShowRequestPermissionRationale(permission)) { needRequestPermissionList.add(permission); }}}return needRequestPermissionList;
    }

    /** * Request permission **@paramPermissions Permissions *@paramRequestCode specifies the requestCode for requesting permission */
    public void requestPermission(String[] permissions, int requestCode) {
        this.REQUEST_CODE_PERMISSION = requestCode;
        if (checkPermissions(permissions)) {
            permissionSuccess(REQUEST_CODE_PERMISSION);
        } else {
            List<String> needPermissions = getDeniedPermissions(permissions);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(needPermissions.toArray(newString[needPermissions.size()]), REQUEST_CODE_PERMISSION); }}}/** * System requests permission callback **@param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSION) {
            if (verifyPermissions(grantResults)) {
                permissionSuccess(REQUEST_CODE_PERMISSION);
            } else{ permissionFail(REQUEST_CODE_PERMISSION); showTipsDialog(); }}}/** * Verify that all permissions are granted **@param grantResults
     * @return* /
    private boolean verifyPermissions(int[] grantResults) {
        for (int grantResult : grantResults) {
            if(grantResult ! = PackageManager.PERMISSION_GRANTED) {return false; }}return true;
    }

    /** * Launches the current app Settings page */
    private void startAppSettings(a) {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }

    /** * Permission obtained successfully **@param requestCode
     */
    public void permissionSuccess(int requestCode) {
        Log.d(TAG, "Permission obtained successfully =" + requestCode);
    }

    /** * Failed to obtain permission **@param requestCode
     */
    public void permissionFail(int requestCode) {
        Log.d(TAG, "Permission failed =" + requestCode);
    }

    /** * Displays a prompt dialog box */
    private void showTipsDialog(a) {
        new AlertDialog.Builder(this)
                .setTitle("Warning message")
                .setMessage("The current application does not have the necessary permissions, so this function is temporarily unavailable. If necessary, please click the "OK" button to go to the setting center for permission authorization.)
                .setNegativeButton("Cancel", (dialog, which) -> {
                })
                .setPositiveButton("Sure", (dialog, which) -> startAppSettings()).show(); }}Copy the code

usage

Layout file


      
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="10dp"
    android:paddingTop="10dp"
    android:paddingRight="10dp"
    android:paddingBottom="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick1"
        android:text="Make a call" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick2"
        android:text="Write an SD card" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick3"
        android:text="Photos" />
</LinearLayout>
Copy the code

MainActivity: inherit MPermissionsActivity

package com.szy.yishopcustomer;

import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends MPermissionsActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /** ** Call **@param view
     */
    public void onClick1(View view) {
        requestPermission(new String[]{Manifest.permission.CALL_PHONE}, 0x0001);
    }

    /** * Write SD card **@param view
     */
    public void onClick2(View view) {
        requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x0002);
    }

    /** ** take photos **@param view
     */
    public void onClick3(View view) {
        requestPermission(new String[]{Manifest.permission.CAMERA}, 0x0003);
    }

    /** * Permission success callback function **@param requestCode
     */
    @Override
    public void permissionSuccess(int requestCode) {
        super.permissionSuccess(requestCode);
        switch (requestCode) {
            case 0x0001:
                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:13468857714"));
                startActivity(intent);
                break; }}}Copy the code

Declare necessary permissions in manifest.xml

    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.CAMERA"/>.Copy the code

Third party library permission library use

We don’t have to build our own wheels. Let’s see what the gods have built

Guo permissionX of god

PermissionX has released a library to simplify the handling of Android runtime permissions. It supports Java and Kotlin. Click the link below to use permissionX

EasyPermission

EasyPermission library EasyPermission library EasyPermission library EasyPermission Github library EasyPermission library EasyPermission Github library EasyPermission library EasyPermission Github library EasyPermission Github library EasyPermission Github library EasyPermission Github library EasyPermission Github library EasyPermission Github library EasyPermission Github library EasyPermission Github