相关文章推荐
会搭讪的石榴  ·  java - How do you fix ...·  1 年前    · 
乐观的桔子  ·  c++ - ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

After requesting permission, the ActivityCompat.OnRequestPermissionsResultCallback sometimes contains multiple grantResults, is it safe to just check the first one?

The training doc check the param like this:

    if (grantResults.length > 0
      && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
      // permission was granted, yay! Do the
      // contacts-related task you need to do.
    } else {
      // permission denied, boo! Disable the
      // functionality that depends on this permission.

but it's not clearly and no documents found.

No, It is not a good way to just check first permission, it might be possible that user have allowed first permission but denied for rest permissions. Here is function i am sharing to check whether all permissions are granted or not

public boolean hasAllPermissionsGranted(@NonNull int[] grantResults) {
    for (int grantResult : grantResults) {
        if (grantResult == PackageManager.PERMISSION_DENIED) {
            return false;
    return true;

and in your onRequestPermissionsResult

if(hasAllPermissionsGranted(grantResults)){
    // all permissions granted
}else {
    // some permission are denied.
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (Arrays.binarySearch(grantResults, -1) >= 0) {
        /* Some permissions are not granted
        request permission again if required */
        return;

The integer array that you can use to validate permissions :

if (Arrays.binarySearch(grantResults, -1) >= 0) { // some permissions are not granted }
                I wouldn't use this because binary search only works on sorted arrays (which grantResults is not). For example, this code will fail for array {0, -1}.
– Bojan Radivojevic
                Apr 14, 2022 at 11:41
   @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE_ASK_PERMISSIONS:
                final int numOfRequest = grantResults.length;
                final boolean isGranted = numOfRequest == 1
                        && PackageManager.PERMISSION_GRANTED == grantResults[numOfRequest - 1];
                if (isGranted) {
                  // you are good to go
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  

requestCode int: Application specific request code to match with a result reported to onRequestPermissionsResult(int, String[], int[]). Should be >= 0.

Since requestCode is Application specific, it's defined by the developer for a specific need, i.e.

public class Main : Activity
    private Bundle _savedInstanceState;        
    private bool _bStorageRationaleBefore;
    private bool _bStorageRationaleAfter;
    private bool _bCameraRationaleBefore;
    private bool _bCameraRationaleAfter;
    private const int ANDROID_PERMISSION_REQUEST_CODE__SDCARD = 2;
    private const int ANDROID_PERMISSION_REQUEST_CODE__CAMERA = 1;
    private const int ANDROID_PERMISSION_REQUEST_CODE__NONE = 0;
    private bool VerifyWriteExternalStoragePermissionRequestResult(string permission, Permission grantResult)
        _bStorageRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);            
        if (permission != Android.Manifest.Permission.WriteExternalStorage || grantResult != Permission.Granted)
            return false;
        return true;
    private bool VerifyCameraPermissionRequestResult(string permission, Permission grantResult)
        _bCameraRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.Camera);
        if (permission != Android.Manifest.Permission.Camera || grantResult != Permission.Granted)
            return false;
        return true;
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
        // note: OnRequestPermissionsResult() runs in a separate thread.
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        bool bStorage = true;
        bool bCamera = true;
        switch (requestCode)
            case ANDROID_PERMISSION_REQUEST_CODE__SDCARD:
                bStorage = VerifyWriteExternalStoragePermissionRequestResult(permissions[0],grantResults[0]);
                break;
            case ANDROID_PERMISSION_REQUEST_CODE__CAMERA:
                bCamera = VerifyCameraPermissionRequestResult(permissions[0], grantResults[0]);
                break;
            case ANDROID_PERMISSION_REQUEST_CODE__SDCARD | ANDROID_PERMISSION_REQUEST_CODE__CAMERA:
                bStorage = VerifyWriteExternalStoragePermissionRequestResult(permissions[0], grantResults[0]);
                bCamera = VerifyCameraPermissionRequestResult(permissions[1], grantResults[1]);
                break;
        // Could check bCamera, but it isn't necessary to continue, and can be prompted for again when camera is needed.
        // Note however that every view that potentially requires the camera will have to:
        ///////////////////////////////////////////////////////////////////
        // 1. Call ApplicationContext.CheckSelfPermission()
        // 2. Call RequestPermissions()
        // 3. Override OnRequestPermissionsResult()
        ///////////////////////////////////////////////////////////////////
        // hence why I'd rather get it done in one spot during startup (main)
        if (bStorage && bCamera)
            RestartActivity();
            // Show error message alert. RestartActivity called from MessageAlertDialogOkClickEventHandler()
            // to prevent race condition between StartActivity() and ShowDialog()
            System.Text.StringBuilder errMsg = new System.Text.StringBuilder();
            string appName = this.ApplicationContext.ApplicationInfo.LoadLabel(PackageManager);
            PermissionGroupInfo pgiStorage = this.PackageManager.GetPermissionGroupInfo(Android.Manifest.Permission_group.Storage, PackageInfoFlags.Permissions);
            PermissionGroupInfo pgiCamera = this.PackageManager.GetPermissionGroupInfo(Android.Manifest.Permission_group.Camera, PackageInfoFlags.Permissions);
            bool bNeverAskForStorage =
                !bStorage && (
                    _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
                    _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
            bool bNeverAskForCamera =
                !bCamera && (
                    _bCameraRationaleBefore == true && _bCameraRationaleAfter == false ||
                    _bCameraRationaleBefore == false && _bCameraRationaleAfter == false
            if (bNeverAskForStorage || bNeverAskForCamera)
                errMsg.Append("To continue, enable " + appName + " Permissions:\n\n");
                if (!bStorage) errMsg.Append("\t* " + pgiStorage.LoadLabel(PackageManager) + "\n");                    
                if (!bCamera) errMsg.Append("\t* " + pgiCamera.LoadLabel(PackageManager) + "\n");
                errMsg.Append("\n(Use \"back button\" when finished to return.)");
                CommonView.ShowMessageAlertDialog(this.FragmentManager, errMsg.ToString(), PermissionMessageAlertDialogOkClickEventHandler2);
            else // if (!bNeverAskForStorage && !bNeverAskForCamera)
                errMsg.Append("To continue, allow " + appName + " to:\n\n");
                if (!bStorage) errMsg.Append("\t* " + pgiStorage.LoadDescription(PackageManager) + "\n");
                if (!bCamera) errMsg.Append("\t* " + pgiCamera.LoadDescription(PackageManager) + "\n");
                CommonView.ShowMessageAlertDialog(this.FragmentManager, errMsg.ToString(), PermissionMessageAlertDialogOkClickEventHandler);
    private void PermissionMessageAlertDialogOkClickEventHandler(object sender, EventArgs e)
        RestartActivity();
    private void PermissionMessageAlertDialogOkClickEventHandler2(object sender, EventArgs e)
        Intent intent = new Intent();
        intent.SetAction(Settings.ActionApplicationDetailsSettings);
        Android.Net.Uri uri = Android.Net.Uri.FromParts("package", this.PackageName, null);
        intent.SetData(uri);            
        StartActivityForResult(intent, 0);
        //RestartActivity();
    protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
        base.OnActivityResult(requestCode, resultCode, data);
        RestartActivity();
    private void RestartActivity()
        Intent restartThisActivityIntent = new Intent(this, this.GetType());
        if (_savedInstanceState != null)
            restartThisActivityIntent.PutExtras(_savedInstanceState);
        StartActivity(restartThisActivityIntent);
    private List<string> GetRequiredPermissions(out int requestCode)
        // Android v6 requires explicit permission granting from user at runtime for security reasons            
        requestCode = ANDROID_PERMISSION_REQUEST_CODE__NONE; // 0
        List<string> requiredPermissions = new List<string>();
        _bStorageRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
        Permission writeExternalStoragePerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage);
        //if(extStoragePerm == Permission.Denied)
        if (writeExternalStoragePerm != Permission.Granted)
            requestCode |= ANDROID_PERMISSION_REQUEST_CODE__SDCARD;
            requiredPermissions.Add(Android.Manifest.Permission.WriteExternalStorage);
        _bCameraRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.Camera);
        Permission cameraPerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.Camera);
        if (cameraPerm != Permission.Granted)
            requestCode |= ANDROID_PERMISSION_REQUEST_CODE__CAMERA;
            requiredPermissions.Add(Android.Manifest.Permission.Camera);
        return requiredPermissions;
    protected override void OnCreate(Bundle savedInstanceState)
        base.OnCreate(savedInstanceState);
            // Android v6 requires explicit permission granting from user at runtime for security reasons
            int requestCode;
            List<string> requiredPermissions = GetRequiredPermissions(out requestCode);
            if (requiredPermissions != null && requiredPermissions.Count > 0)
                //if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__SDCARD)
                if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__CAMERA)
                    _savedInstanceState = savedInstanceState;
                    RequestPermissions(requiredPermissions.ToArray(), requestCode);
                    return;
        catch (Exception ex)
            Global.LogFile.WriteEntry(ex.ToString());
            CommonView.ShowMessageAlertDialog(this.FragmentManager, ex.Message);
            return;
        OnCreate2(savedInstanceState);
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.