Android onRequestPermissionsResult grantResults size > 1
После запроса разрешения https://developer.android.com/reference/android/support/v4/app/ActivityCompat.OnRequestPermissionsResultCallback.html иногда содержит несколько 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.
}
но это не ясно и никаких документов не найдено.
3 ответа
Нет, это не хороший способ просто проверить первое разрешение, возможно, пользователь разрешил первое разрешение, но запретил остальные. Вот функция, которой я делюсь, чтобы проверить, предоставлены ли все разрешения или нет
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.
}
Самый короткий способ убедиться, что все разрешения предоставлены пользователем.
@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 }
Согласно документам для запроса разрешения
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);
}
}
Вы можете проверить их все
@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);
}