# # # 1. The overview


The video explanation has been recorded for several days, but RECENTLY I have been busy with Unity3D, even singles Day writing, last time we only wrote Android 6.0 runtime permission processing analysis, but did not do the code encapsulation, this time we do a thorough processing. Attached video interpretation address: http://pan.baidu.com/s/1bpqqkGn

# # # 2. Frame encapsulation


2.1. A simple example

Public class MainActivity extends AppCompatActivity {// Request code for making a phone request private static final int CALL_PHONE_REQUEST_CODE = 0x0011; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
    }

    public void phoneClick(View view){
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) ! = PackageManager.PERMISSION_GRANTED){ Toast.makeText(this,"Application permission", Toast.LENGTH_SHORT).show();
            ActivityCompat.requestPermissions(this,
                    new String[]{"Manifest.permission.CALL_PHONE"}, CALL_PHONE_REQUEST_CODE);
        }else{ callPhone(); }} /** * Dial **/ private voidcallPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:147****2514");
        intent.setData(data);
        startActivity(intent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == CALL_PHONE_REQUEST_CODE){
            if(grantResults ! =null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission Granted callPhone(); }else {
                // Permission Denied
                Toast.makeText(this,"Permission denied.",Toast.LENGTH_SHORT).show(); }}}}Copy the code

Which are copied from the previous, did not make any processing, if every time to apply for permission to place all need to do so, that is more troublesome, so we are sure to phoneClick () and onRequestPermissionsResult () code for processing, then to be processed into what look like? Of course all code can be optimized into one line, that’s what they say.

2.1. To determine the way to encapsulate, there are a lot of github, Chinese, Japanese, Korean people have it, this is not a joke really have, here I use reflection + annotations to achieve. 2.2. Parameter passing and how to pass it we definitely need to create a new class, but what parameter to pass? The first parameter reflects the class this, the second parameter request code is used to listen for feedback processing, and the third parameter passes an array of request permissions using what method is passed so? You can write a static method in the utility class and shove it in. But in this case we can use chain calls which we use all the time, like Okhttp, Gilde, even Android AlertDialogs, which can install B

public class PermissionHelper { // 1. Object Fragment or Activity 1.2. int Request code 1.3. String [] private Object mObject; private int mRequestCode; private String[] mRequestPermission; private PermissionHelper(Object object){ this.mObject = object; Public static void requestPermission(Activity Activity,int requestCode,String) [] public static void requestPermission(Activity Activity,int requestCode,String) permissions){ PermissionHelper.with(activity).requestCode(requestCode). requestPermission(permissions).request(); } public static void requestPermission(Fragment fragment,int requestCode,String[] permissions){ PermissionHelper.with(fragment).requestCode(requestCode). requestPermission(permissions).request(); } public static PermissionHelper with(Activity Activity){returnnew PermissionHelper(activity); } // Upload a Fragment public static PermissionHelper with(Fragment){returnnew PermissionHelper(fragment); } public PermissionHelper requestCode(int requestCode){this.mRequestCode = requestCode;returnthis; } // add requestPermission array public PermissionHelper requestPermission(String... permissions){ this.mRequestPermission = permissions;returnthis; } /** * 3.1 Request permission */ public voidrequest() {// 3.2 Check whether the current version is 6.0 or laterif(! PermissionUtils. IsOverMarshmallow ()) {/ / 3.3 if not more than 6.0 So directly reflect the execution method for execution method / / execution method is not sure So we can only adopt the way of annotation method to make a mark, // Then execute through reflection. Annotations + reflection to perform the Activity inside the callPhone PermissionUtils. ExecuteSucceedMethod (mObject mRequestCode);return; }}}Copy the code

2.2. Deal with the following version 6.0 For the following version 6.0, we can directly reflect call execution methods of success, if reflection is not very understanding can take a look at this video tutorial: http://pan.baidu.com/s/1bpqqkGn

/** * Public static void executeSucceedMethod(Object reflectObject, [] methods = reflectobject.getClass ().getDeclaredMethods(); // Look for our marked methodfor (Method method:methods){
            Log.e("TAG",method+""); Permissionsucceedmethod = method.getannotation (permissionsucceed.class);if(succeedMethod ! = null) {/ / represents the method played tag / / and we request code must be the same requestCode int methodCode = succeedMethod. RequestCode ();if(methodCode == requestCode){// This is the successful method we are looking for // reflection executes the method log.e ("TAG"."Found the way:"+method); executeMethod(reflectObject,method); }}}} /** * Reflection executes this Method */ private static void executeMethod(Object reflectObject,Method Method) {// Reflection executes this Method The second argument is the argument to the reflection method try {method.setaccessible (true); // Allow the execution of the private method method.invoke(reflectObject,new Object[]{}); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }}Copy the code

2.3. Handles versions 6.0 and later

/** * 3.1 Request permission */ public voidrequest() {// 3.2 Check whether the current version is 6.0 or laterif(! PermissionUtils. IsOverMarshmallow ()) {/ / 3.3 if not more than 6.0 So directly reflect the execution method for execution method / / execution method is not sure So we can only adopt the way of annotation method to make a mark, // Then execute through reflection. Annotations + reflection to perform the Activity inside the callPhone PermissionUtils. ExecuteSucceedMethod (mObject mRequestCode);return; List<String> deniedPermissions = List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mObject,mRequestPermission); // 3.3.1 If granted then we directly execute method reflection to get the execute methodif(deniedPermissions. The size () = = 0) {/ / all are granted PermissionUtils executeSucceedMethod (mObject mRequestCode); }else{/ / 3.3.2 rainfall distribution on 10-12 if not granted Then we will apply for permission to apply for permission to ActivityCompat. RequestPermissions (PermissionUtils. GetActivity (mObject), deniedPermissions.toArray(new String[deniedPermissions.size()]), mRequestCode); }}Copy the code

2.4. To deal with the callback If a user will agree or reject the callback onRequestPermissionsResult (), we certainly need to make it handle, this method is very simple:

*/ public static void requestPermissionsResult(Object Object,int requestCode, String[] Permissions) {// Get permissions again that were not granted List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(object,permissions);if(deniedPermissions. The size () = = 0) {/ / permissions users agree that given PermissionUtils executeSucceedMethod (object, requestCode); }else{/ / your application with user permissions from the disagree PermissionUtils. ExecuteFailMethod (object, requestCode); }}Copy the code

2.5. Final example

Public class MainActivity extends AppCompatActivity {// Request code for making a phone request private static final int CALL_PHONE_REQUEST_CODE = 0x0011; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
    }

   public void phoneClick(View view){
        PermissionHelper.with(this).requestCode(CALL_PHONE_REQUEST_CODE)
                .requestPermission(Manifest.permission.CALL_PHONE).request();
    }

    @PermissionSucceed(requestCode =  CALL_PHONE_REQUEST_CODE)
    private void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:147****2514");
        intent.setData(data);
        startActivity(intent);
    }

    @PermissionFail(requestCode = CALL_PHONE_REQUEST_CODE)
    private void callPhoneFail(){
        Toast.makeText(this,"You have refused to make a call.", Toast.LENGTH_SHORT).show(); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { PermissionHelper.requestPermissionsResult(this, CALL_PHONE_REQUEST_CODE,permissions); }}Copy the code

At the end of the processing access request again will be a lot easier, one line of code to solve the problem, anyway, the other people all say so, we can even put the onRequestPermissionsResult processing wrote BaseActivity (), because the permissions encapsulation part I don’t have written to the it infrastructure, I’m not going to deal with that.