Understanding the Android 6 permission method

眉间皱痕 提交于 2019-12-30 20:31:13

问题


I am trying to take an image from Gallery and set it to an imageview but in Android 6 there are some permission problems. Below is the method to ask for the permission. Should I ask for read external storage or write external storage?

Here is what I have done so far:

    private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;


    public void getPermissionToReadExternalStorage() {

    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {

        if (shouldShowRequestPermissionRationale(
                Manifest.permission.READ_EXTERNAL_STORAGE)) {

            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    READ_CONTACTS_PERMISSIONS_REQUEST);
        }}}
    @Override
            public void onRequestPermissionsResult(int requestCode,
                                                   @NonNull String permissions[],
                                                   @NonNull int[] grantResults){
                // Make sure it's our original READ_CONTACTS request
                if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
                    if (grantResults.length == 1 &&
                            grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show();

                    } else {
                        Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                }
            }

Now my on click listener to pick data from the Gallery:

     pro.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            intent.setType("image/*");
            if (android.os.Build.VERSION.SDK_INT >= 23) {
                getPermissionToReadExternalStorage();
                if (getPermissionToReadExternalStorage () this???? <==)
                startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
            } else {
                startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0);
        }}

    });
    return v;
}

Now I want to get result of the method getPermissionToReadExternalStorage() so I can start the Activity for picking gallery for Android 6. How can I get the result of the void class? And another thing is do I have to write method for every permission my app asks for?


回答1:


So I have completely rewritten the code to request permissions. Now it supports requesting for multiple permissions and running code with proper result. Also it works with preMarshmallow devices, so you don't have to check and copy the code in that case.

First, create an Activity class with this code (You can extend any king of activity you need, e.g. AppCompatActivity):

public abstract class PermissionActivity extends AppCompatActivity {

    private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>();

    @SuppressWarnings("unused")
    public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) {
        requestPermissions(requestCode, requestPermissions, null, permissionListener);
    }

    @SuppressWarnings("unused")
    public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) {
        final int[] grantResults = new int[requestPermissions.length];

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ArrayList<String> list_notGranted = new ArrayList<>();

            for (String requestPermission : requestPermissions)
                if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED)
                    list_notGranted.add(requestPermission);

            if (list_notGranted.size() > 0) {
                permissionListeners.add(permissionListener);

                requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]);

                if (message != null) {
                    boolean shouldShowRequestPermissionRationale = false;

                    for (String permission : requestPermissions)
                        if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
                            shouldShowRequestPermissionRationale = true;
                            break;
                        }

                    if (shouldShowRequestPermissionRationale) {
                        final String[] f_requestPermissions = requestPermissions;

                        AlertDialog.Builder builder = new AlertDialog.Builder(this);

                        builder.setMessage(message);

                        DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {

                            @TargetApi(Build.VERSION_CODES.M)
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                switch (which) {
                                    case DialogInterface.BUTTON_POSITIVE:
                                        PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode);
                                        break;
                                    default:
                                        for (int i = 0; i < grantResults.length; i++)
                                            grantResults[i] = PackageManager.PERMISSION_DENIED;

                                        if (permissionListener != null)
                                            permissionListener.onResult(requestCode, f_requestPermissions, grantResults);
                                        break;
                                }
                            }
                        };

                        builder.setPositiveButton("OK", onClickListener);
                        builder.setNegativeButton("Cancel", onClickListener);

                        builder.show();
                    } else {
                        super.requestPermissions(requestPermissions, requestCode);
                    }
                } else {
                    super.requestPermissions(requestPermissions, requestCode);
                }
            } else {
                for (int i = 0; i < grantResults.length; i++)
                    grantResults[i] = PackageManager.PERMISSION_GRANTED;

                if (permissionListener != null)
                    permissionListener.onResult(requestCode, requestPermissions, grantResults);
            }
        } else {
            if (permissionListener != null) {
                for (int i = 0; i < grantResults.length; i++)
                    grantResults[i] = PackageManager.PERMISSION_GRANTED;

                permissionListener.onResult(requestCode, requestPermissions, grantResults);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
        for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext(); ) {
            PermissionListener permissionListener = it.next();
            if (permissionListener.onResult(requestCode, permissions, grantResults)) {
                it.remove();
            }
        }
    }

    public interface PermissionListener {

        boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults);

    }
}

If you want to request permissions from Fragments, add this class:

public class PermissionFragment extends Fragment {

    @SuppressWarnings("unused")
    public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) {
        requestPermissions(requestCode, requestPermissions, null, permissionListener);
    }

    @SuppressWarnings("unused")
    public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) {
        ((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener);
    }
}

Your Activities and Fragments should extend these classes instead of the standart ones.

Now you are ready to request the permissions by calling a method:

requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener)

If the permission is required for the app to work, you should call this method and specify the message saying why the permission is required.

requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener)

DONT MISSCALL THE DEFAULT METHOD, WHICH IS

// DON'T USE THIS ONE!
requestPermissions(String[] requestPermissions, int requestCode)
// DON'T USE THIS ONE!

Here is the example of requesting contacts:

private void requestAndLoadContacts() {
    String[] permissions = new String[]{Manifest.permission.READ_CONTACTS};

    requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() {

        @Override
        public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) {
            // Check if the requestCode is ours
            if (requestCode == REQUEST_PERMISSIONS_CONTACTS) {
                // Check if the permission is correct and is granted
                if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission granted
                    // Calling a method to actually load the contacts
                    loadContacts();
                } else {
                    // Permission not granted
                    Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show();
                }

                return true;
            }

            return false;
        }
    });
}

NOTE: When you implement the PermissionListener, don't forget to return true when the requestCode is the correct one, otherwise the PermissionListener won't be removed from the ArrayList and you'll most likely get a small memory leak.




回答2:


EDIT

I have rewritted the code and posted in another answer.

Old answer:

Yes, you have to check and ask for permission every time.

Usually I write the code like this:

private int requestPermissionCode;
private Runnable requestPermissionRunnable;

private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) {
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            requestPermissionCode = requestCode;
            requestPermissionRunnable = codeToRun;

            requestPermissions(new String[]{requestPermission},
                    requestCode);
        }
    } else {
        codeToRun.run();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String permissions[],
                                       @NonNull int[] grantResults) {
    if (requestCode == requestPermissionCode) {
        if (grantResults.length == 1 &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            if (requestPermissionRunnable != null)
                requestPermissionRunnable.run();
        } else {
            Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show();
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

and run it like this:

    runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() {

        @Override
        public void run() {
            // your code here
        }
    });

I am sure it is not a best way, but at least it gives a possibility to request permission and make actions easier.




回答3:


Initialize Your Permission

private static final int INITIAL_REQUEST = 1337;
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2;
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3;

private static final String[] INITIAL_PERMS = {
        Manifest.permission.GET_ACCOUNTS,
        Manifest.permission.INTERNET,
        Manifest.permission.ACCESS_FINE_LOCATION
};

Check for device and Request for permissions

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) {
            requestPermissions(INITIAL_PERMS, INITIAL_REQUEST);
        }
    }

Check Permission is granted Or not

private boolean canAccessAccounts() {

    return (hasPermission(Manifest.permission.GET_ACCOUNTS));
}
private boolean canAccessLocation() {

    return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
private boolean canAccessInternet() {
    return (hasPermission(Manifest.permission.INTERNET));
}
private boolean hasPermission(String perm) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm));
    }
    return (true);
}

Update Permissions and Check method for permissions onRequestPermissionsResult

 void UpdatePermissions(){

    canAccessInternet();
    canAccessLocation();
    canAccessInternet();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    UpdatePermissions();
    switch(requestCode) {
        case GET_ACCOUNTS:
            if (canAccessAccounts()) {

            }
            else {

            }
            break;

        case LOCATION_REQUEST:
            if (canAccessLocation()) {

            }
            else {

            }
            break;

        case INITIAL_REQUEST:
            if(canAccessInternet()){

            }else {

            }
            break;

    }
}


来源:https://stackoverflow.com/questions/34211693/understanding-the-android-6-permission-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!