Geolocation doesn't work iOS PCL Xamarin forms

2019-05-29 21:15发布

问题:

I'm trying to get device location with help of this example https://github.com/XLabs/Xamarin-Forms-Labs/wiki/Geolocator. This works on simulators , but on iPad Air doesn't work. My info.plist file containing all necessary keys for location., NSLocationUsageDescription and NSLocationWhenInUseUsageDescription

in code

if (this.manager.RespondsToSelector(new Selector("requestWhenInUseAuthorization")))
{
    this.manager.RequestWhenInUseAuthorization();
} 

piece of code where using Geolocator object..

IGeolocator geolocator = null;
geolocator = DependencyService.Get<IGeolocator>();
if (geolocator != null)
{
    if (geolocator.IsGeolocationEnabled)
    {
        try
        {
            if (!geolocator.IsListening)
                geolocator.StartListening(1000, 1000);

            var task = await geolocator.GetPositionAsync(10000, CancellationToken.None);

            if(task != null)
            {
                this.Position = task;
            }

but LocationUpdated event never fire......

Location on device is on.

If anyone have similar issue....... please help..... Once, this work on simulators.

I use VS 2013, Xamarin 3.7, Xamarin.iOS 8.4 , iOS 8.1 on iPad Air.

回答1:

So this works fine in the iPad air simulator? It sounds like an issue specific to the device you are using. Maybe someone hit "Cancel" on the allow location popup?

Go to Settings->General->Restrictions->Location Services. Make sure everything is turned on and allowed for your app. I would also try another app, and make sure location is working in that app.



回答2:

Did you try without the Xlabs geoocator service, because last time I tried, it was buggy.

Beside, in your code I dont see that you attache to the PositionChanged Event handler :

_geolocator.PositionChanged += OnPositionChanged;

This is needed if you want continuous location upadte.

Without using XLabs I would do something like this :

  public bool Start(ActivityType activity = ActivityType.Other, bool alsoWhenInBackground = false, LocationAccuracy accuracy = LocationAccuracy.AccurracyBestForNavigation,
                      double minDistanceBetweenUpdatesInMeters = 0, TimeSpan? maxDelayBetweenUpdates = null)
    {
        if (manager != null)
            return true;

        manager = new CLLocationManager();
        manager.Failed += (sender, args) => FireError(args.Error.ToString());
        manager.LocationsUpdated += (sender, args) => FireLocationUpdated(args.Locations);
        //manager.AuthorizationChanged

        manager.ActivityType = (CLActivityType)activity;
        manager.DesiredAccuracy = Accuracies[(int)accuracy];
        if (maxDelayBetweenUpdates != null || minDistanceBetweenUpdatesInMeters > double.Epsilon)
            manager.AllowDeferredLocationUpdatesUntil(minDistanceBetweenUpdatesInMeters, (maxDelayBetweenUpdates ?? TimeSpan.Zero).TotalSeconds);

        if (alsoWhenInBackground)
            manager.PausesLocationUpdatesAutomatically = true;

        //Required: ask for authorization
        if (AuthorizationStatus == AuthorizationStatus.NotDetermined)
            AskAuthorization(alsoWhenInBackground);

        var authStatus = AuthorizationStatus;
        if (authStatus < AuthorizationStatus.AuthorizedAlways && authStatus != AuthorizationStatus.NotDetermined)
        {
            System.Diagnostics.Debug.WriteLine("user denied access to location");

            return false;
        }
        if (authStatus == AuthorizationStatus.AuthorizedWhenInUse && alsoWhenInBackground)
        {
            System.Diagnostics.Debug.WriteLine("alsoWhenInBackground is true, but user denied access to location in background");

            return false;
        }

        manager.StartUpdatingLocation();
        return true;
    }

public bool AskAuthorization(bool alsoWhenInBackground = false)
    {
        if (AuthorizationStatus != AuthorizationStatus.NotDetermined)
            return false;

        if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
        {
            if (alsoWhenInBackground)
                manager.RequestAlwaysAuthorization();
            else
                manager.RequestWhenInUseAuthorization();
        }

        return true;
    }