【问题标题】:Xamarin: GoogleApiClient is null after OnConnected & OnLocationChanged never calledXamarin:在 OnConnected 和 OnLocationChanged 从未调用之后,GoogleApiClient 为空
【发布时间】:2016-12-31 15:48:11
【问题描述】:

我正在使用 Xamarin 构建一个应该使用位置服务的 Android 应用程序。

在 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 仍然是 != null。

这个方法永远不会被调用:

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

当我从 UI 调用此方法时,apiClient 为空:

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

【问题讨论】:

  • 我假设您通过表单的依赖服务调用getAdresse?你在哪里定义apiClient?如果它在您的 MainActivity 类中,并且您也在为 getAdresse 实现 DS 接口,您需要重新考虑您的方法,因为您正在“重新创建”您的 MainActivity
  • 你是对的。我通过 DependencyService 调用 getAddresse,并且在我的 MainActivity 中定义了 apiClient。正确的方法是什么?

标签: android xamarin xamarin.android google-play-services


【解决方案1】:

您可以使用在 Android Application 子类等中定义的静态变量...但这是我的首选方式... ;-)

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.Forms 项目中的用法:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多