2
\$\begingroup\$

Here is my class that handle all MarshMallow Permissions I prefer separate it class as I will call its methods in all my apps.

At first I get used to check permission by this way:

private void CheckPermissionGranted() {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, CHECK_PERMISSION_CODE);
            return;
        }
    }
}

and here is my class to handle all permissions:

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;

/**
 * Created by mina on 10/9/2016.
 */

public class MarshMallowPermission {

    public static final int RECORD_PERMISSION_REQUEST_CODE = 1;
    public static final int WRITE_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
    public static final int READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 3;
    public static final int CAMERA_PERMISSION_REQUEST_CODE = 4;
    Activity activity;

    public MarshMallowPermission(Activity activity) {
        this.activity = activity;
    }

    public boolean checkPermissionForRecord(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }

    public boolean checkPermissionForWriteExternalStorage(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }
    public boolean checkPermissionForReadExternalStorage(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }

    public boolean checkPermissionForCamera(){
        int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
        if (result == PackageManager.PERMISSION_GRANTED){
            return true;
        } else {
            return false;
        }
    }

    public void requestPermissionForRecord(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.RECORD_AUDIO)){
            Toast.makeText(activity, "Microphone permission needed for recording. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.RECORD_AUDIO},RECORD_PERMISSION_REQUEST_CODE);
        }
    }

    public void requestPermissionForWriteExternalStorage(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
            Toast.makeText(activity, "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},WRITE_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
        }
    }
    public void requestPermissionForReadExternalStorage(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.READ_EXTERNAL_STORAGE)){
            Toast.makeText(activity, "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
        }
    }

    public void requestPermissionForCamera(){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
            Toast.makeText(activity, "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
        }
    }
}

I check permission when use click button to upload Image from Camera or image library

private void selectImage() {
    final CharSequence[] items = {str_camera, str_image_lib,
            str_cancel};

    AlertDialog.Builder builder = new AlertDialog.Builder(UploadActivity.this);
    builder.setTitle("Add Files!");
    builder.setItems(items, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int item) {
            if (items[item].equals(str_camera)) {
                if (!marshMallowPermission.checkPermissionForCamera()) {
                    marshMallowPermission.requestPermissionForCamera();
                    return;
                }
                dispatchTakePictureIntent();
            } else if (items[item].equals(str_image_lib)) {
                if (!marshMallowPermission.checkPermissionForReadExternalStorage()) {
                    marshMallowPermission.requestPermissionForReadExternalStorage();
                    return;
                }
                enableBrowseFile();
            } else if (items[item].equals(str_cancel)) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}

if permission not granted I request permission , if granted I call methods that required this permission to run

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case MarshMallowPermission.READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                enableBrowseFile();
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    marshMallowPermission.requestPermissionForReadExternalStorage();
                }
            }

            break;
        case MarshMallowPermission.CAMERA_PERMISSION_REQUEST_CODE:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                dispatchTakePictureIntent();
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    marshMallowPermission.requestPermissionForCamera();
                }
            }

            break;
    }
}
\$\endgroup\$
2
\$\begingroup\$

A few things:

public static final int RECORD_PERMISSION_REQUEST_CODE = 1;
public static final int WRITE_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
public static final int READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 3;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 4;

This is a collection of compile-time constant expressions. You associate those to "magic" int-values. Instead of that an enum would provide type-safe request codes. For interoperability purposes with the Android API, you can expose a method requestCode():

public enum RequestCode {
    Record(1), WriteExternalStorage(2), ReadExternalStorage(3), Camera(4);

    private final int code;
    private RequestCode(int code){
        this.code = code;
    }
    public int requestCode() {
        return code;
    }
}

This makes your code a tad easier to read IMO. Also it provides proper encapsulation instead of relying on constant class members.


Your checkPermissionFor*() methods all follow a certain pattern. You can drastically collapse these methods. The first step is seeing that the following code samples are equivalent:

if (result == PackageManager.PERMISSION_GRANTED) {
    return true;
} else {
    return false;
}
return result == PackageManager.PERMISSION_GRANTED;

The next step is seing the fact that you're "computing" result in always the same way. The only difference is the Manifest.permission you pass to checkSelfPermission. You can further simplify by using import static like the following:

import static android.support.v3.content.ContextCompat.checkSelfPermission;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.Manifest.permission;

// ...
public boolean checkPermissionForRecord() {
    return checkSelfPermission(activity, permission.RECORD_AUDIO) == PERMISSION_GRANTED;
}

And suddenly the information benefit that your method provides vanished. The only real gain remaining from encapsulating this is now the fact that you provide a thin abstraction layer.

IMO that's not sufficient justification for that class to exist, at least not with the given usage code. If you use this in more than a handful of places it might be useful, but right now this class seems like it's useless baggage to me.

\$\endgroup\$
-2
\$\begingroup\$

This may help you find the solution'

PermissionsMashmallow.Class handle mashmallow permission

public class PermissionsMashmallow {
            Context mContext;

            public PermissionsMashmellow(Context context) {
                mContext = context;
                MY_PERMISSIONS_REQUEST_READ_CONTACTS = requestCode;
            }

      /*  *//**
         * Check permission for in phone
         *
         * @return true or false
         *//*
        public boolean weHavePermission(String READ_CONTACTS) {
            return ContextCompat.checkSelfPermission(mContext, READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
        }

        *//**
         * request permission from for reading contacts in phone
         *//*
        public void requestForPermission(String READ_CONTACTS, int MY_PERMISSIONS_REQUEST) {
            ActivityCompat.requestPermissions((Activity) mContext, new String[]{READ_CONTACTS}, MY_PERMISSIONS_REQUEST);
        }

    */

        public  boolean hasPermissions(String... permissions) {
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && mContext != null && permissions != null) {
                for (String permission : permissions) {
                    if (ActivityCompat.checkSelfPermission(mContext, permission) != PackageManager.PERMISSION_GRANTED) {
                        return false;
                    }
                }
            }
            return true;
        }

        public  void  requestPermissions( String[] PERMISSIONS,int PERMISSION_ALL) {
            // The request code used in ActivityCompat.requestPermissions()
    // and returned in the Activity's onRequestPermissionsResult()
                ActivityCompat.requestPermissions((Activity) mContext, PERMISSIONS, PERMISSION_ALL);
        }
    }

Inside your Activity

 PermissionsMashmallow     permissionsMashmallow = new PermissionsMashmallow(this);
private final int PERMISSION_ALL = 2;
String[] PERMISSIONS = { Manifest.permission.WRITE_EXTERNAL_STORAGE};
 private void CheckPermissionGranted() {

        if (permissionsMashmallow.hasPermissions(PERMISSIONS)) {
            //  permission granted
        } else {
            // request permission 
            permissionsMashmallow.requestPermissions(PERMISSIONS, PERMISSION_ALL);
        }
    }
\$\endgroup\$
  • 1
    \$\begingroup\$ Why are these changes better than the original? We usually prefer more review with code suggestions. The point being not just to improve the current application but enlighten for future coding as well. \$\endgroup\$ – mdfst13 Oct 17 '16 at 11:50
  • \$\begingroup\$ number of lines of code are less since there is a common method provided for all permission \$\endgroup\$ – Rissmon Suresh Oct 17 '16 at 12:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.