Android onRequestPermissionsResult grantResults size > 1

前端 未结 4 1005
庸人自扰
庸人自扰 2020-12-18 03:51

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

相关标签:
4条回答
  • 2020-12-18 03:58

    According to the docs for requestPermissions

    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();
            }
            else
            {
                // 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);
    
            try
            {
                // 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);
        }
    }
    
    0 讨论(0)
  • 2020-12-18 04:02

    You can check them all

       @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);
            }
    
    0 讨论(0)
  • 2020-12-18 04:07

    The shortest way you can make sure all the permissions are granted by the user.

    @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 }
    
    0 讨论(0)
  • 2020-12-18 04:10

    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.
    }
    
    0 讨论(0)
提交回复
热议问题