Will Nasby
Will Nasby

Reputation: 1148

Requesting Android permissions in a class (Xamarin)

I'm trying to request a permission at runtime for my app. I use a service provider to talk between the portable class and Android.

I start by calling this code on button press in the PCL:

using (new Busy(this))
                {
                    var locationHelper = scope.Resolve<ILocationHelper>();
                    locationHelper.GetLocation(this);
                }

This calls my Android level service:

public class AndroidLocationHelper : ILocationHelper, ILocationListener
    {

        readonly string[] PermissionsLocation =
        {
            Manifest.Permission.AccessCoarseLocation
        };
        const int RequestLocationId = 0;

public void GetLocation(SearchViewModel viewModel)
        {
            try
            {
                const string permission = Manifest.Permission.AccessCoarseLocation;
                if (((int)Build.VERSION.SdkInt < 23) || (CheckSelfPermission(permission) == Permission.Granted))
                {
                }
                else
                    RequestPermissions(PermissionsLocation, RequestLocationId);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error while getting Location service");
                Debug.WriteLine(ex.Message);
                Messaging.AlertUser("There was an error with determining your location");
            }
        }

However, I get two errors on CheckSelfPermission and RequestPermissions. These two methods are only available to activities. The code works fine in MainActivity; however, I want to ask for permissions when the user hits a button, not in OnCreate or OnResume, etc.

Thanks for any help.

Upvotes: 2

Views: 13054

Answers (5)

envyM6
envyM6

Reputation: 1237

It's dead simple

public bool CheckPermission()
    {
        const string permission = Manifest.Permission.ReceiveSms;
        return ContextCompat.CheckSelfPermission(Forms.Context, permission) == (int) Permission.Granted;
    }

Upvotes: -1

ricsierics
ricsierics

Reputation: 301

To expound Rafael Steil's answer, I tried the suggested CurrentActivityPlugin and it worked on me. In my case I am trying to execute a voice call which needs CALL_PHONE permission. Here is the code snippet in your case: I used the ContextCompat & ActivityCompat so that I don't need to check the VERSION.SdkInt

        using Plugin.CurrentActivity;

        public void GetLocation(SearchViewModel viewModel){

           var context = CrossCurrentActivity.Current.AppContext; 
           var activity = CrossCurrentActivity.Current.Activity;
           int YOUR_ASSIGNED_REQUEST_CODE = 9;

           if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.AccessCoarseLocation) == (int)Android.Content.PM.Permission.Granted)
           {
               //Permission is granted, execute stuff   
           }
           else
           {                
               ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.AccessCoarseLocation }, YOUR_ASSIGNED_REQUEST_CODE);
           }
        }

Upvotes: 0

Damien Doumer
Damien Doumer

Reputation: 2266

In your Android project, You can use this and use the Dependency Service to call it in Xamarin.Forms PCL project later:

var thisActivity = Forms.Context as Activity;
ActivityCompat.RequestPermissions(thisActivity, new string[] { 
Manifest.Permission.AccessFineLocation }, 1);
ActivityCompat.RequestPermissions(thisActivity,
new String[] { Manifest.Permission.AccessFineLocation },
1);

Upvotes: 4

Will Nasby
Will Nasby

Reputation: 1148

Rafael came up with a solution but I found another option that is a lot less effort just using MessagingCenter. In the MainActivity's OnCreate add a receiver that runs all the location code, that way you have access to all of the activities methods (and there are a bunch of tutorials on doing location services in MainActivity). Then add the Send inside of your service (the class).

Upvotes: 1

Rafael Steil
Rafael Steil

Reputation: 4697

You can try with ContextCompat.CheckSelfPermission, passing the application context, like this:

ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission)

Update

In case of ActivityCompat.RequestPermissions, which requires an activity reference, you can keep track of the current activity. There is a very handy lib for that, called "CurrentActivityPlugin". You can find at https://github.com/jamesmontemagno/CurrentActivityPlugin

Upvotes: 2

Related Questions