Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
292 views
in Technique[技术] by (71.8m points)

c# - Location permission for Android above 6.0 with Xamarin.Forms.Maps

I'm trying to implement a Xamarin.Forms application using Xamarin.Forms.Maps, however I always fall into the exception:

Java.Lang.SecurityException: my location requires permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION

I have already tried following the steps in this tutorial https://blog.xamarin.com/requesting-runtime-permissions-in-android-marshmallow/ but did not get results.

Would anyone have something more consistent to help me?

What I'm intending is to use an application very close to Uber and I can not progress if I can not get the location permissions.

My MainPage looks like this in my PCL:

public partial class MainPage: ContentPage
????{
????????public MainPage ()
????????{
????????????InitializeComponent ();
????????????var map = new Map ()
????????????{
????????????????MapType = MapType.Street,
????????????????IsShowingUser = true
????????????};

????????????var stack = new StackLayout {Spacing = 0};
????????????stack.Children.Add (map);

????????????Content = stack;
????????}
????}

My MainActivity class in Xamarin.Android looks like this:

[Activity (Label = "ExampleGeolocation", Icon = "@ drawable / icon",
??????????????Theme = "@ style / MainTheme", MainLauncher = true,
??????????????ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

????public class MainActivity: global :: Xamarin.Forms.Platform.Android.FormsAppCompatActivity, ActivityCompat.IOnRequestPermissionsResultCallback
????{
????????View layout;
????????const int RequestLocationId = 0;
????????readonly string [] PermissionsLocation = {Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation};

????????protected override void OnCreate (Bundle bundle)
????????{
????????????TabLayoutResource = Resource.Layout.Tabbar;
????????????ToolbarResource = Resource.Layout.Toolbar;

????????????base.OnCreate (bundle);

????????????global :: Xamarin.Forms.Forms.Init (this, bundle);
????????????global :: Xamarin.FormsMaps.Init (this, bundle);

????????????Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;

????????????SetStatusBarColor (Android.Graphics.Color.Black);
????????????LoadApplication (new App ());
????????}

????????public override async void OnRequestPermissionsResult (int requestCode, string [] permissions, [GeneratedEnum] Permission [] grantResults)
????????{
????????????switch (requestCode)
????????????{
????????????????case RequestLocationId:
????????????????????{
????????????????????????if (grantResults [0] == Permission.Granted)
????????????????????????{
????????????????????????????var snack = Snackbar.Make (layout, "Location Permission is Available.", Snackbar.LengthShort);
????????????????????????????snack.Show ();

????????????????????????????await GetLocationAsync ();
????????????????????????}
????????????????????????else
????????????????????????{
????????????????????????????var snack = Snackbar.Make (layout, "Location Permission Denied", Snackbar.LengthShort);
????????????????????????????snack.Show ();
????????????????????????}
????????????????????}

????????????????????break;
????????????}
????????}

????????async Task TryGetLocationAsync ()
????????{
????????????if ((int) Build.VERSION.SdkInt <23)
????????????{
????????????????await GetLocationAsync ();
????????????????return;
????????????}

????????????await GetLocationPermissionAsync ();
????????}

????????async Task GetLocationPermissionAsync ()
????????{
????????????const string permission = Manifest.Permission.AccessFineLocation;

????????????if (CheckSelfPermission (permission) == Permission.Granted)
????????????{
????????????????await GetLocationAsync ();
????????????????return;
????????????}

????????????if (ShouldShowRequestPermissionRationale (permission))
????????????{
????????????????Snackbar.Make (layout, "You must allow the application to access your location options.", Snackbar.LengthIndefinite)
????????????????????????.SetAction ("OK", v => RequestPermissions (PermissionsLocation, RequestLocationId))
????????????????????????.Show();

????????????????return;
????????????}

????????????RequestPermissions (PermissionsLocation, RequestLocationId);
????????}

????????async Task GetLocationAsync ()
????????{
????????????try
????????????{
????????????????var locator = CrossGeolocator.Current;
????????????}
????????????catch (Exception e)
????????????{
????????????????e.ToString ();
????????????????throw new NotImplementedException ();
????????????}
????????}
????};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Location permission for Android above 6.0 with Xamarin.Forms.Maps

You wrote a lot of code about permission but I can't find where you request the permission, you need request the permission before you use it.

When you set IsShowingUser property to true, you should request the permission first, here are three solutions.

Solution 1:

I notice that you are using PermissionsPlugin in your code, if you need request this permission in PCL, you could refer to the PermissionsPlugin official sample.

Add this code in your MainActivity:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

Request permission when you need it:

try
{
    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
    if (status != PermissionStatus.Granted)
    {
        if(await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
        {
            await DisplayAlert("Need location", "Gunna need that location", "OK");
        }

        var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
        status = results[Permission.Location];
     }

     if (status == PermissionStatus.Granted)
     {
         //Permission granted, do what you want do.
     }
     else if(status != PermissionStatus.Unknown)
     {
         await DisplayAlert("Location Denied", "Can not continue, try again.", "OK");
     }
}
catch (Exception ex)
{
    //...
}

Solution 2:

When you open your application, request the permission first, in MainActivity OnStart method:

protected override void OnStart()
{
    base.OnStart();

    if (ContextCompat.CheckSelfPermission(this, permission) != Permission.Granted)
    {
        ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation }, 0);
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("Permission Granted!!!");
    }
}

Solution 3:

Use DependencyService to request the permission when you need it, here is the sample related to the tutorial you have read. In this example, it requests permission when execute this line:

buttonGetLocation.Click += async (sender, e) => await TryGetLocationAsync();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...