Android onRequestPermissionsResult grantResults size > 1

前端 未结 4 1011
庸人自扰
庸人自扰 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 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 requiredPermissions = new List();
    
            _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 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);
        }
    }
    

提交回复
热议问题