Search code examples
c#androidxamarinxamarin.formsxamarin.android

Xamarin Android Request Runtime Permissions Not Working


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!


Solution

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