Xamarin: GoogleApiClient является null после OnConnected & OnLocationChanged никогда не вызывается

Я создаю Android-приложение с Xamarin, которое должно использовать Службы определения местоположения.

В OnCreate я создаю GoogleApiClient:

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        global::Xamarin.Forms.Forms.Init (this, bundle);
        LoadApplication (new KMN.App ());

        apiClient = new GoogleApiClient.Builder(this, this, this).AddApi(LocationServices.API).Build();
        apiClient.Connect();
    }

apiClient != null после этого. Чем я занимаюсь:

    public void OnConnected(Bundle connectionHint)
    {
        LocationRequest locRequest = new LocationRequest();
        locRequest.SetPriority(LocationRequest.PriorityBalancedPowerAccuracy);
        locRequest.SetFastestInterval(500);
        locRequest.SetInterval(1000);

        LocationServices.FusedLocationApi.RequestLocationUpdates(apiClient, locRequest, this);
    }

Здесь apiClient еще != недействительный.

Этот метод никогда не вызывается:

    public void OnLocationChanged(Android.Locations.Location location)
    {
        LastLocation = location;
    }

Когда я вызываю этот метод из пользовательского интерфейса, apiClient равен null:

    public Adresse getAdresse()
    {
        if (LastLocation!= null)
        { 
            return new Adresse()
            {
                Latitude = LastLocation.Latitude,
                Longitude = LastLocation.Longitude
            };
        }
        else
        {
            return new Adresse()
            {
                Latitude = 0,
                Longitude = 0
            };
        }
    }

1 ответ

  1. Вы можете использовать статические переменные, определенные в Applicationподклассе Android и т.д… Но это мой предпочтительный способ… 😉

    Интерфейс DS и некоторые вспомогательные классы:

    public interface ILocationService : IDisposable
    {
        Task<bool> Init();
        MyLocation Currentlocation();
        void Subscribe(EventHandler handler);
        void Unsubscribe(EventHandler handler);
    }
    
    public class MyLocation
    {
        public MyLocation(double Latitude, double Longitude)
        {
            this.Latitude = Latitude;
            this.Longitude = Longitude;
        }
    
        public double Latitude { get; private set; }
        public double Longitude { get; private set; }
    }
    
    public class LocationEventArgs<T> : EventArgs
    {
        public T EventData { get; private set; }
    
        public LocationEventArgs(T EventData)
        {
            this.EventData = EventData;
        }
    }
    

    Реализация Зависимостей Android:

    public class LocationService : Java.Lang.Object, 
            ILocationService,
            GoogleApiClient.IConnectionCallbacks,
            GoogleApiClient.IOnConnectionFailedListener,
            Android.Gms.Location.ILocationListener,
            IDisposable
    {
        bool _init;
        GoogleApiClient gClient;
        LocationRequest locRequest;
        ManualResetEventSlim resetEvent;
        EventHandler eventHandler;
    
        public async Task<bool> Init()
        {
            await Task.Run(() =>
            {
                if (!_init)
                {
                    resetEvent = new ManualResetEventSlim();
                    gClient = new GoogleApiClient.Builder(Forms.Context, this, this).AddApi(LocationServices.API).Build();
                    _init = true;
                }
                resetEvent.Reset();
                gClient.Connect();
                resetEvent.Wait();
            });             
            return gClient.IsConnected;
        }
    
        public new void Dispose()
        {
            resetEvent?.Dispose();
            if (gClient != null)
                LocationServices.FusedLocationApi.RemoveLocationUpdates(gClient, this);
            gClient?.Dispose();
            base.Dispose();
        }
    
        public void OnConnected(Bundle connectionHint)
        {
            resetEvent.Set();
        }
    
        public void OnConnectionFailed(ConnectionResult result)
        {
            resetEvent.Set();
        }
    
        public void OnConnectionSuspended(int cause)
        {
            LocationServices.FusedLocationApi.RemoveLocationUpdates(gClient, this);
        }
    
        public void OnLocationChanged(Android.Locations.Location location)
        {
            Log.Debug("SO", location.ToString());
            eventHandler?.Invoke(null, new LocationEventArgs<MyLocation>(new MyLocation(location.Latitude, location.Longitude)));
        }
    
        public void Subscribe(EventHandler locationHandler)
        {
            locRequest = new LocationRequest();
            locRequest.SetPriority(LocationRequest.PriorityBalancedPowerAccuracy);
            locRequest.SetFastestInterval(100);
            locRequest.SetInterval(5000);
    
            eventHandler += locationHandler;
            LocationServices.FusedLocationApi.RequestLocationUpdates(gClient, locRequest, this);
        }
    
        public void Unsubscribe(EventHandler locationHandler)
        {
            LocationServices.FusedLocationApi.RemoveLocationUpdates(gClient, this);
            eventHandler -= locationHandler;
        }
    
        public MyLocation Currentlocation()
        {
            if (gClient != null)
            {
                var lastLocation = LocationServices.FusedLocationApi.GetLastLocation(gClient);
                Log.Debug("SO", lastLocation.ToString());
    
                if (lastLocation != null)
                    return new MyLocation(lastLocation.Latitude, lastLocation.Longitude);
            }
            return null;
        }
    }
    

    Использование в Xamarin.Формы проекта:

    var startLocationUpdates = new Command(async () =>
    {
        if (await DependencyService.Get<ILocationService>().Init())
        {
            // Subscribe to the location change events...
            DependencyService.Get<ILocationService>().Subscribe((sender, e) =>
            {
                var loc = (e as LocationEventArgs<MyLocation>).EventData;
                System.Diagnostics.Debug.WriteLine($"{loc.Latitude}:{loc.Longitude}");
            });
    
            // Or just grab the Fused-based LastLocation (it might not be  available!)
            var loc2 = DependencyService.Get<ILocationService>().Currentlocation();
            if (loc2 != null)
                System.Diagnostics.Debug.WriteLine($"{loc2?.Latitude}:{loc2?.Longitude}");
        }
    });
    var button = new Button { Text = "Start Location Updates", Command = startLocationUpdates };