Android onRequestPermissionsResult grantResults size> 1

После запроса разрешения ActivityCompat.OnRequestPermissionsResultCallback иногда содержит несколько grantResults. Безопасно ли просто проверять первый?

учебный документ проверьте параметр следующим образом:

    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.
    }

но это не понятно и никаких документов не найдено.

Ответ 1

Нет, это не лучший способ проверить первое разрешение. Возможно, пользователь разрешил первое разрешение, но отказал в разрешении на отдых. Вот функция, которую я разделяю, чтобы проверить, предоставлены ли все разрешения или нет.

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

и в onRequestPermissionsResult

if(hasAllPermissionsGranted(grantResults)){
    // all permissions granted
}else {
    // some permission are denied.
}

Ответ 2

Вы можете проверить их все

   @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);
        }

Ответ 3

В соответствии с документами для requestPermissions

requestCode int: Код запроса приложения для соответствия с результат сообщается onRequestPermissionsResult (int, String [], int []). Должно быть >= 0.

Так как requestCode является специфичным для приложения, он определяется разработчиком для конкретной потребности, то есть

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);
    }
}

Ответ 4

Кратчайший способ убедиться, что все разрешения предоставлены пользователем.

@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;
    }
}

Целочисленный массив, который вы можете использовать для проверки прав доступа:

if (Arrays.binarySearch(grantResults, -1) >= 0) { // some permissions are not granted }