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