How to elegantly apply for Android runtime permissions

Keywords: Mobile Android github Fragment

To reproduce this article, you need to indicate the source: WeChat public number EAWorld, violators must be prosecuted.

 

Preface:

 

Android is a privilege-separated operating system where each application has its own unique system identity.By default, no application has permission to perform any action that adversely affects other applications, operating systems, or users.This includes reading or writing the user's private data (such as contacts or e-mail), reading or writing files from other applications, performing network access, and keeping the device awake.

- Cited from Google's Android development documentation

 

Catalog:

 

1. Evolution of Android privileges

2. Application for Runtime Permissions

3. Android Rights Open Source Library

4. How to gracefully apply for permissions

 

1. Evolution of Android privileges

 

Before Android 6.0

 

Prior to Android 6.0, application permissions could be obtained by simply declaring them in the code in AndroidManifest.xml, without requiring the user's consent.Some App s have applied for a lot of permissions at once, and even some tool apps have applied for sensitive permissions such as text messaging, recording, reading mobile files.Of course, that was also the time when rogue software was most prevalent. Countless apps were sneaking chickens and dogs in the background to steal user-sensitive data.

 

After Android 6.0

 

After Android 6.0, app rights were divided by Google into two categories, normal and dangerous.Normal privileges are declared in AndroidManifest.xml and dangerous privileges need to be applied to the user before they can be used, with the user's consent.If the operation is executed without applying to the user, the application flips back with a direct error.

 

Dangerous Permissions and Rights Groups:

 

 

2. Application for Runtime Permissions

 

Principles for using Android privileges

 

According to Google's official documentation, the following four principles are recommended:

 

  • Use only the permissions required for the application to function properly

  • Note the permissions required by the library

  • Open and transparent

  • Allow system explicit access

 

Simply put, don't ask for permission unless you really need it.

 

How to apply for permission

 

Determine whether permissions have been granted

int hasPermission=ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.WRITE_EXTERNAL_STORAGE);if (hasPermission == PackageManager.PERMISSION_GRANTED) {  //Permission acquired}else{  //No permissions obtained      }

 

Apply for permission

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MainActivity.RequestPermissionCode);

 

Register callback in Activity

@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {  if (requestCode == RequestPermissionCode){    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){      //User agrees to permission request    }else{      //User rejected permission request, recommend explaining permission use to user    }  }}

 

3.Android Rights Open Source Library

 

From the example above, you can see that the application permission code is cumbersome, you need to judge the permissions, apply for permissions, and register the callback of the result of the permission application in the Activity.There are many open source libraries in the community with run-time privileges, the four with more star ts on github below.

 

 

PermissionsDispatcher

 

This library is based on annotations and supports Java/Kotlin.Since you are annotating the method you are implementing to request permissions, the code is relatively concise, and we will basically use the following annotations.

 

 

Similarly, after you have written the method you want to execute after you have applied for permissions, you must also register callbacks in the Activity's onRequestPermissionsResult.

 

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults)        // NOTE: delegate the permission handling to generated function        onRequestPermissionsResult(requestCode, grantResults)    }

 

RxPermissions

 

It's also an excellent open source library that provides a RxJava-style permission application method with concise code that can be initialized with AppCompatActivity and called anywhere.However, you need to introduce the RxJava library.

 

final RxPermissions rxPermissions = new RxPermissions(this);// Must be done during an initialization phase like onCreaterxPermissions    .request(Manifest.permission.CAMERA)    .subscribe(granted -> {        if (granted) { // Always true pre-M           // I can control the camera now        } else {           // Oups permission denied        }});

 

easypermissions

 

The method provided in googlesamples uses EasyPermissions.requestPermissions to apply for permissions and also requires a callback to be registered in the Activity's onRequestPermissionsResult.

 

AndPermission

 

Only androidx is supported, Activity is also required to initialize, and the code is concise.

 

AndPermission.with(this)  .runtime()  .permission(Permission.Group.STORAGE)  .onGranted(permissions -> {    // Storage permission are allowed.  })  .onDenied(permissions -> {    // Storage permission are not allowed.  })  .start();

 

In general, each library has its own advantages and disadvantages, you can choose the best library for your project according to your specific needs.

 

4. How to gracefully apply for permissions

 

Slot spitting: Open source library code is cumbersome, documentation is limited, and problem solving is not timely.

 

Each project has different needs, and these rich open source libraries may still not meet our requirements, not only for permission applications, but also for other functions.Next, I'll take you by hand to make a wheel that simplifies the permission request code.

 

Overall thinking

 

Most open source libraries register callbacks in Activity on RequestPermissionsResult when requesting permissions, which I hate because the code is too intrusive.

 

If I encapsulate an interface to get locations, this is a stand-alone method, typically written in LocationUtils.java, and any class class may call my method, which results in LocationUtils not having an Activity to receive data for the onRequestPermissionsResult callback.I believe this is also one of the major issues most developers face.

 

So in the application, I can load a Fragment (similar to the RxPermissions idea), apply for permissions in the fragment, and the onRequestPermissionsResult callback is also placed in the fragment.This allows me to load this fragment anywhere that an Activity exists to request permissions and remove it when the request is complete.

 

public static void requestPermission(final Activity context, final String[] permissions, PermissionCallback permissionCallback) {        permissionFragment.setOnAttachCallback(new FragmentAttachCallback() {            @Override            public void onAttach() {                permissionFragment.requestPermission(permissions);            }        });       permissionFragment.setOnPermissionCallback(permissionCallback);       FragmentTransaction fragmentTransaction = context.getFragmentManager().beginTransaction();       //Let me see your 777 in the comments area       fragmentTransaction.add(permissionFragment, "permissionFragment@777").commit();

 

Of course, we can also use the getTop Activity method to let the privilege library get Activeness on the top of the stack by itself, so that only callbacks to the privileges and privilege results that need to be applied for can be passed in.

 

PermissionAnywhere.requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}                        , permissionCallback);

 

PermissionCallback returns the caller's click-to-agree rights, the user's click-to-deny rights, and the user's click-to-click rights that are no longer prompted and denied.

 

public interface PermissionCallback {    void onComplete(List<String> grantedPermissions, List<String> deniedPermissions, List<String> alwaysDeniedPermissions);}

 

Usage method

 

1. Increase in the root directory build.gradle

allprojects {    repositories {        ...        maven { url 'https://jitpack.io' }    }}

 

2. Increase Dependency

dependencies {    implementation 'com.github.mingyuers:PermissionAnywhere:latest.release'}

 

Code download address

 

The complete code above is open source to github:

https://github.com/mingyuers/PermissionAnywhere

Welcome to study, star, pr.

 

extend

 

Actually, you can also use Activity of 1px to apply for permissions, so can you apply for permissions in Application?Will other questions be raised?Welcome to the message area for discussion.

 

About Author: Ming Yue, Senior Development Engineer of Puyuan Mobile Team, long-term commitment to IT technology research, product design and development, good at Java, NodeJs, ReactNative and other fields of technology.She has participated in the implementation of Shenzhen Deng, Taibao and other mobile projects, and participated in the design and development of Mobile 8.0 mobile platform.

About EAWorld: Micro Services, DevOps, Data Governance, Mobile Architecture Original Technology Sharing.

 

Course Preview!On April 13 (Friday) at 14:30 pm, PYD Mobile Development Engineer Paddlefish shared "Analyzing RN Component Life Cycle from Mobile8.0 Platform and Micro-Application", reply "YG+Micro-Signal" on this public number and complete the registration immediately!

Posted by deRusett on Mon, 13 Apr 2020 19:55:13 -0700