4

so I am trying to ask the user for permission to use Location on the app that I am trying to create. I have included the permission in Android Manifest

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 

And in my SplashActivity page where the Splash Screen is and where I want my permissions to appear to the user i have put the following code in:

namespace Cabiee.Droid { [Activity(Theme = "@style/Theme.Splash", MainLauncher = true, NoHistory = true, Icon = "@drawable/CabieBackground")] public class SplashActivity : Activity { protected async override void OnCreate(Bundle savedInstanceState) { await TryToGetPermissions(); base.OnCreate(savedInstanceState); System.Threading.Thread.Sleep(500); StartActivity(typeof(Login)); // Create your application here } #region RuntimePermissions async Task TryToGetPermissions() { if ((int)Build.VERSION.SdkInt >= 23) { await GetPermissionsAsync(); return; } } const int RequestLocationId = 0; readonly string[] PermissionsGroupLocation = { //TODO add more permissions Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation, }; async Task GetPermissionsAsync() { const string permission = Manifest.Permission.AccessFineLocation; if (CheckSelfPermission(permission) == (int)Android.Content.PM.Permission.Granted) { //TODO change the message to show the permissions name Toast.MakeText(this, "Special permissions granted", ToastLength.Short).Show(); return; } if (ShouldShowRequestPermissionRationale(permission)) { //set alert for executing the task AlertDialog.Builder alert = new AlertDialog.Builder(this); alert.SetTitle("Permissions Needed"); alert.SetMessage("The application need special permissions to continue"); alert.SetPositiveButton("Request Permissions", (senderAlert, args) => { RequestPermissions(PermissionsGroupLocation, RequestLocationId); }); alert.SetNegativeButton("Cancel", (senderAlert, args) => { Toast.MakeText(this, "Cancelled!", ToastLength.Short).Show(); }); Dialog dialog = alert.Create(); dialog.Show(); return; } RequestPermissions(PermissionsGroupLocation, RequestLocationId); } public override async void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { switch (requestCode) { case RequestLocationId: { if (grantResults[0] == (int)Android.Content.PM.Permission.Granted) { Toast.MakeText(this, "Special permissions granted", ToastLength.Short).Show(); } else { //Permission Denied :( Toast.MakeText(this, "Special permissions denied", ToastLength.Short).Show(); } } break; } //base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } #endregion } 

However, the user isn't being asked for the permssions. I think it might have something to do with the await TryToGetPermissions(); line towards the start of the code which is not actually calling the TryToGetPermissions and therefore it is not working.

Any help would be greatly appreciated.

Thanks!

2
  • 2
    generally, you should request permission X when your app is doing something that requires permission X. You don't just request everything when the app starts. Or worse, BEFORE your app has actually finished starting. Commented Mar 14, 2019 at 21:59
  • Yes i see, you're right. I got a Google Map so maybe move the code to the page where the map is would be better but currently, I'm having problems with that so I had it at the SplashScreen. Commented Mar 14, 2019 at 22:01

2 Answers 2

2

I have a working solution for the exact same thing which is something as follows:

In your OnCreate method check for existing permissions:

 if (!(CheckPermissionGranted(Manifest.Permission.AccessCoarseLocation) && CheckPermissionGranted(Manifest.Permission.AccessFineLocation))) { RequestLocationPermission(); } else { InitializeLocationManager(); } InitPageWidgets(); 

Where Check permission Granted is a method something like this:

 [Export] public bool CheckPermissionGranted(string Permissions) { // Check if the permission is already available. if (ActivityCompat.CheckSelfPermission(this, Permissions) != Permission.Granted) { return false; } else { return true; } } 

And the Request permission code looks something like this:

 private void RequestLocationPermission() { if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation)) { // Provide an additional rationale to the user if the permission was not granted // and the user would benefit from additional context for the use of the permission. // For example if the user has previously denied the permission. ActivityCompat.RequestPermissions(this, PermissionsLocation, REQUEST_LOCATION); } else { // Camera permission has not been granted yet. Request it directly. ActivityCompat.RequestPermissions(this, PermissionsLocation, REQUEST_LOCATION); } } 
Sign up to request clarification or add additional context in comments.

3 Comments

Which ActivityCompat i need? Visual Studio asks me if i want to use namespace Android.Support.V4.App or AndroidX.Core.App
@АндрейГолубев I would suggest you use AndroidX.Core.App but in case if that does not work only then use the other one
Thank you for your response, I've already solved my problem with Xamarin.Essentials
1

If you don't require async/await, below is what I did in my app where I needed Camera permissions. It works great for my needs and maybe it will for you as well.

Your implementation would be even simpler as you wouldn't need to iterate multiple results in OnRequestPermissionsResult(). I had to do that as my app needs to save the pictures, and therefore needs both the Camera and WriteExternalStorage permissions before I can load the camera interface/activity.

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.Landscape)] public class MainLoaderActivity : AppCompatActivity { private const string LOG_TAG = "CAMERA2_LOG"; private const int PERMISSION_REQUEST_CODE_CAMERA_USAGE = 4500; // Arbitrary number to identify our permissions required for camera app usage private Button btnLoadCameraActivity; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.main_loader); btnLoadCameraActivity = FindViewById<Button>(Resource.Id.btnLoadCameraActivity); btnLoadCameraActivity.Click += btnLoadCameraActivity_Click; } private void btnLoadCameraActivity_Click(object sender, EventArgs e) { // Using the camera on Android 6.0 and later requires a run-time permissions granting by the user. // So, check to see if user manually enabled in Settings, or previously was prompted in this app and was granted access. If not, we'll prompt them... if (CheckSelfPermission(Android.Manifest.Permission.Camera) == Permission.Granted && CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage) == Permission.Granted) { // We have both permissions necessary to run the Camera interface... StartActivity(typeof(CameraActivity)); return; } // If we get here, at least one of the required permissions hasn't been approved, so find out which one and request accordingly... var listPermissions = new System.Collections.Generic.List<string>(); // Build array of permissions needed for Camera usage if (CheckSelfPermission(Android.Manifest.Permission.Camera) != Permission.Granted) { Log.Warn(LOG_TAG, "CheckSelfPermission(Camera) not yet granted - will prompt user for permission"); listPermissions.Add(Android.Manifest.Permission.Camera); } if (CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage) != Permission.Granted) { Log.Warn(LOG_TAG, "CheckSelfPermission(WriteExternalStorage) not yet granted - will prompt user for permission"); listPermissions.Add(Android.Manifest.Permission.WriteExternalStorage); } // Make the request with the permissions needed...and then check OnRequestPermissionsResult() for the results RequestPermissions(listPermissions.ToArray(), PERMISSION_REQUEST_CODE_CAMERA_USAGE); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults) { Log.Info(LOG_TAG, $"OnRequestPermissionsResult(requestCode={requestCode} - Permissions Count={permissions.Length} - GrantResults Count={grantResults.Length})"); switch (requestCode) { // To use the camera, the user must grant privs to the Camera as well as writing to external storage, so this case checks both case PERMISSION_REQUEST_CODE_CAMERA_USAGE: { for (var i = 0; i < permissions.Length; i++) { Log.Info(LOG_TAG, $"Checking permission for {permissions[i]}..."); if (grantResults[i] != Permission.Granted) { Log.Info(LOG_TAG, $"Permission Denied for {permissions[i]}!"); Toast.MakeText(this, "You must approve all permissions prompted to use the camera.", ToastLength.Long).Show(); return; } Log.Info(LOG_TAG, $"Permission Granted for {permissions[i]}."); } // If we get here then all the permissions we requested were approved and we can now load the Camera interface StartActivity(typeof(CameraActivity)); break; } } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.