如何在Android M中一次请求中检查多个权限?

69

我想在单个请求中使用以下权限:

  1. android.permission.CAMERA
  2. android.permission.WRITE_EXTERNAL_STORAGE

请不要改变原意,保留HTML标记。

ActivityCompat.requestPermissions(Activity activity,new String permisionList[],int permissionRequestcode);

但是我的问题是有时我只请求一个权限,我了解到组权限,但它只适用于由开发人员决定的相同组,比如CONTACT_GROUP: read_contact,write_contact等。

我想创建自定义组权限,它只需要一个请求,并且只提供一个响应。

谢谢


3
抱歉,您不能这样做。每个群组都有自己的权限对话框,必须进行调用。 - Ragaisis
@Ragaisis 我想在一个请求中显示所有的权限,我知道如果我请求多个权限,但只得到一个结果。 - Zala Janaksinh
轻松请求多个权限的方法,请查看 https://github.com/sachinvarma/EasyPermission - Sachin Varma
16个回答

76

你可以在一个请求中同时询问多个权限(来自不同的组)。为此,您需要将所有权限添加到字符串数组中,并将其作为requestPermissions API的第一个参数提供,如下所示:

requestPermissions(new String[]{
                                Manifest.permission.READ_CONTACTS,
                                Manifest.permission.ACCESS_FINE_LOCATION},
                        ASK_MULTIPLE_PERMISSION_REQUEST_CODE);

这样做时,您将看到权限弹出窗口堆叠在一起。当然,您需要处理每个权限的接受和拒绝(包括“不再询问”)选项。同样的内容也已经在这里美妙地解释了。


9
请完整阅读我的问题。我想在一个请求中检查所有权限,而不是多个对话框。还有,你的链接与我的问题无关。抱歉。 - Zala Janaksinh
太棒了!谢谢! - Federico Alvarez
2
我必须添加 this,否则它就无法工作 ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, ...} ,ASK_MULTIPLE_PERMISSION_REQUEST_CODE); - Yonjuni
@Yonjuni 它没有检查权限列表是否已授予。 - kyawagwin

31

首先初始化权限请求代码

public  static final int PERMISSIONS_MULTIPLE_REQUEST = 123;

检查安卓版本

 private void checkAndroidVersion() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        checkPermission();

    } else {
        // write your logic here
    }

}

检查多个权限代码

 private void checkPermission() {
    if (ContextCompat.checkSelfPermission(getActivity(),
            Manifest.permission.READ_EXTERNAL_STORAGE) + ContextCompat
            .checkSelfPermission(getActivity(),
                    Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {

        if (ActivityCompat.shouldShowRequestPermissionRationale
                (getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) ||
                ActivityCompat.shouldShowRequestPermissionRationale
                        (getActivity(), Manifest.permission.CAMERA)) {

      Snackbar.make(getActivity().findViewById(android.R.id.content),
                    "Please Grant Permissions to upload profile photo",
                    Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            requestPermissions(
                                    new String[]{Manifest.permission
                                            .READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
                                    PERMISSIONS_MULTIPLE_REQUEST);
                        }
                    }).show();
        } else {
            requestPermissions(
                    new String[]{Manifest.permission
                            .READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
                    PERMISSIONS_MULTIPLE_REQUEST);
        }
    } else {
        // write your logic code if permission already granted
    }
}

用户授权后回调方法

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String[] permissions, @NonNull int[] grantResults) {

    switch (requestCode) {
        case PERMISSIONS_MULTIPLE_REQUEST:
            if (grantResults.length > 0) {
               boolean cameraPermission = grantResults[1] == PackageManager.PERMISSION_GRANTED;
               boolean readExternalFile = grantResults[0] == PackageManager.PERMISSION_GRANTED;

                if(cameraPermission && readExternalFile)
                {
                    // write your logic here 
                } else {
                    Snackbar.make(getActivity().findViewById(android.R.id.content),
                        "Please Grant Permissions to upload profile photo",
                        Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
                        new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                requestPermissions(
                                        new String[]{Manifest.permission
                                                .READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
                                        PERMISSIONS_MULTIPLE_REQUEST);
                            }
                        }).show();
                }
           }
           break;
    }
}

3
依赖于一个魔法数字(PERMISSION_GRANTED = 0)是相当靠不住的。 - zyamys
请求多个权限的方式相当混乱。 - M. Usman Khan
请告诉我为什么? - mohit
太棒了!完美地运行了。 - Annie
这个答案有一个 bug...如果你连续两次拒绝某个权限,当你在 Snackbar 上点击启用时,Snackbar 会一遍又一遍地出现。 - Ahmed Elsayed

6
在当前阶段,没有任何方法可以规避同时向不同组请求权限的要求。这是安卓运行时权限所发展出来的本质,为了给用户选择接受哪些权限的权利。当然,如果不接受应用所需的全部权限,可能会导致应用无法正常工作。
相机和写入外部存储都被视为危险权限,并分别属于不同的组,因此都需要运行时权限请求
一旦为特定组授予权限,就无需在应用运行期间再次请求,或者在默认设置下被撤销之前。

enter image description here

enter image description here

您唯一能做的就是要求用户接受默认决策,这些决策可以通过“不再询问”选项来撤销。

enter image description here


5

我曾经遇到相同的问题,后来发现了这个

你可以依次请求多个权限,如果用户拒绝了你的权限,还可以添加监听器弹出 snackbar。

dexter_sample


他没有说要引入一个库。 - sajjad Yosefi

4

如果需要多个权限,您可以使用以下代码:

final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;

private void insertDummyContactWrapper() {
    List<String> permissionsNeeded = new ArrayList<String>();

    final List<String> permissionsList = new ArrayList<String>();
    if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
        permissionsNeeded.add("GPS");
    if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
        permissionsNeeded.add("Read Contacts");
    if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
        permissionsNeeded.add("Write Contacts");

    if (permissionsList.size() > 0) {
        if (permissionsNeeded.size() > 0) {
            // Need Rationale
            String message = "You need to grant access to " + permissionsNeeded.get(0);
            for (int i = 1; i < permissionsNeeded.size(); i++)
                message = message + ", " + permissionsNeeded.get(i);
            showMessageOKCancel(message,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                        }
                    });
            return;
        }
        requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
        return;
    }

    insertDummyContact();
}

private boolean addPermission(List<String> permissionsList, String permission) {
    if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(permission);
        // Check for Rationale Option
        if (!shouldShowRequestPermissionRationale(permission))
            return false;
    }
    return true;
}

如果您正在使用Marshmallow,则必须使用这些单独的权限。 - dipali

4

我这里有一个简单的解决方案,-(多个权限检查)

String[] permissions = new String[]{
  Manifest.permission.WRITE_CALL_LOG,
  Manifest.permission.READ_CALL_LOG,
  Manifest.permission.READ_CONTACTS,
  Manifest.permission.WRITE_CONTACTS}; // Here i used multiple permission check

然后在Oncreate中调用它。
 if (checkPermissions()) { //  permissions  granted.
    getCallDetails();
 }

最后,复制以下代码

private boolean checkPermissions() {
  int result;
  List<String> listPermissionsNeeded = new ArrayList<>();

   for (String p : permissions) {
     result = ContextCompat.checkSelfPermission(getApplicationContext(), p);
     if (result != PackageManager.PERMISSION_GRANTED) {
       listPermissionsNeeded.add(p);
     }
   }

   if (!listPermissionsNeeded.isEmpty()) {
     ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MULTIPLE_PERMISSIONS);
     return false;
   }
     return true;
}


@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  switch (requestCode) {
    case MULTIPLE_PERMISSIONS: {
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  // permissions granted.
           getCallDetails(); // Now you call here what ever you want :)
        } else {
             String perStr = "";
               for (String per : permissions) {
                   perStr += "\n" + per;
                }   // permissions list of don't granted permission
              }
            return;
          }
       }
    }

如果可以的话,为什么这个条件只测试索引0?if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) - Čamo
onrequestpermission不起作用,因为它只检查第一个granResult... - Umberto Migliore
MULTIPLE_PERMISSIONS 的值是多少? - KernelPanic

3

2
我遇到了相同的问题,以下是我想出的解决方法:
public boolean checkForPermission(final String[] permissions, final int permRequestCode, int msgResourceId) {
        final List<String> permissionsNeeded = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            final String perm = permissions[i];
            if (ContextCompat.checkSelfPermission(getActivity(), permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                if (shouldShowRequestPermissionRationale(permissions[i])) {
                    final AlertDialog dialog = AlertDialog.newInstance( getResources().getString(R.string.permission_title), getResources().getString(msgResourceId) );
                    dialog.setPositiveButton("OK", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            // add the request.
                            permissionsNeeded.add(perm);
                            dialog.dismiss();
                        }
                    });
                    dialog.show( getActivity().getSupportFragmentManager(), "HCFAlertDialog" );
                } else {
                    // add the request.
                    permissionsNeeded.add(perm);
                }
            }
        }

        if (permissionsNeeded.size() > 0) {
            // go ahead and request permissions
            requestPermissions(permissionsNeeded.toArray(new String[permissionsNeeded.size()]), permRequestCode);
            return false;
        } else {
            // no permission need to be asked so all good...we have them all.
            return true;
        }
    }

你可以像下面这样调用上述方法:

if ( checkForPermission( new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, 
Manifest.permission.CAMERA}, REQUEST_PERMISSION_EXTERNAL_STORAGE_RESULT, R.string.permission_image) ) {
                        // DO YOUR STUFF

                    }

你检查过你的代码了吗?在这段代码中,也会多次显示本地权限对话框。 - Zala Janaksinh
1
@Zala Janaksinh 是的...安卓会单独显示权限,但你只需发出一个请求。 - velval
我知道这个问题,所以这是我的问题。兄弟,也许安卓在下一个更新中会解决这个问题。 - Zala Janaksinh

1
检查多个权限并请求未被授予的权限。
 public void checkPermissions(){
    if(ContextCompat.checkSelfPermission(getApplicationContext(),
            Manifest.permission.WRITE_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.CAMERA)==PackageManager.PERMISSION_GRANTED){
        //Do_SOme_Operation();
    }else{
        requestStoragePermission();
    }
}

public void requestStoragePermission(){
    ActivityCompat.requestPermissions(this
            ,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA},1234);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode){
        case 1234:if(grantResults[0]==PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
  // Do_SOme_Operation();
        }

        default:super.onRequestPermissionsResult(requestCode,permissions,grantResults);
    }
}

0

为不同类型的权限添加通用代码。复制粘贴并进行微小更改。请阅读下面代码中的“TODO”注释。

将以下活动设置为您的启动器活动:

public class PermissionReqActivity extends AppCompatActivity {

    private static final int CODE_WRITE_SETTINGS_PERMISSION = 332;
    private static String[] PERMISSIONS_ALL = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; //TODO You can Add multiple permissions here.
    private static final int PERMISSION_REQUEST_CODE = 223;
    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_permission_req);
        context = this;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            boolean allPermissionsGranted = true;
            ArrayList<String> toReqPermissions = new ArrayList<>();

            for (String permission : PERMISSIONS_ALL) {
                if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                    toReqPermissions.add(permission);

                    allPermissionsGranted = false;
                }
            }
            if (allPermissionsGranted)
                //TODO Now some permissions are very special and require Settings Activity to launch, as u might have seen in some apps. handleWriteSettingsPermission() is an example for WRITE_SETTINGS permission. If u don't need very special permission(s), replace handleWriteSettingsPermission() with initActivity().
                handleWriteSettingsPermission();
            else
                ActivityCompat.requestPermissions(this,
                        toReqPermissions.toArray(new String[toReqPermissions.size()]), PERMISSION_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_REQUEST_CODE) {
            boolean allPermGranted = true;
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, "Permissions not granted: " + permissions[i], Toast.LENGTH_LONG).show();
                    allPermGranted = false;
                    finish();
                    break;
                }
            }
            if (allPermGranted)
                handleWriteSettingsPermission();//TODO As mentioned above, use initActivity() here if u dont need very special permission WRITE_SETTINGS
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void handleWriteSettingsPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (Settings.System.canWrite(context)) {
                initActivity();
            } else {
                Toast.makeText(this, "Please Enable this permission for " +
                        getApplicationInfo().loadLabel(getPackageManager()).toString(), Toast.LENGTH_LONG).show();
                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                intent.setData(Uri.parse("package:" + context.getPackageName()));
                startActivityForResult(intent, CODE_WRITE_SETTINGS_PERMISSION);
            }
        }
    }

//TODO You don't need the following onActivityResult() function if u dont need very special permissions.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && requestCode == CODE_WRITE_SETTINGS_PERMISSION) {
            if (Settings.System.canWrite(this))
                initActivity();
            else {
                Toast.makeText(this, "Permissions not granted: " + Manifest.permission.WRITE_SETTINGS, Toast.LENGTH_LONG).show();
                finish();
            }
        }
    }

    private void initActivity() {
        startActivity(new Intent(this, MainActivity.class));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接