【问题标题】:Using gps location system services dependency injection使用gps定位系统服务依赖注入
【发布时间】:2015-04-22 15:37:44
【问题描述】:

我希望使用 Xamarin 的依赖注入获取特定于平台的位置详细信息,但遇到了问题。很可能是做错了。

这是我目前的设置:

nuMaps/Interfaces/ILocationService.cs

using Xamarin.Forms.Maps;

namespace nuMaps
{
    public interface ILocationService
    {
        void initLocationService();
        Position getCurrentPosition();
    }
}

nuMaps/nuMaps.Droid/Interfaces/LocationService.cs

using System;
using nuMaps;
using nuMaps.Droid;
using Xamarin.Forms.Maps;
using Android.App;
using Android.Gms.Common;
using Android.Gms.Common.Apis;
using Android.Gms.Location;
using Android.Locations;
using Android.Widget;

[assembly: Xamarin.Forms.Dependency (typeof (LocationService))]

namespace nuMaps.Droid
{
    public class LocationService : Java.Lang.Object, ILocationService, IGoogleApiClientConnectionCallbacks, IGoogleApiClientOnConnectionFailedListener, Android.Gms.Location.ILocationListener
    {
        readonly IGoogleApiClient _googleApiClient;
        readonly LocationRequest _locRequest;
        Position _currentPosition;
        Location _currentLocation;

        public LocationService()
        {
            Console.WriteLine ("LocationService constructor");
            _currentPosition = new Position (0, 0);

            _googleApiClient = new GoogleApiClientBuilder (Xamarin.Forms.Forms.Context)
                .AddApi (LocationServices.Api)
                .AddConnectionCallbacks (this)
                .AddOnConnectionFailedListener (this)
                .Build ();

            _locRequest = new LocationRequest ();
        }

        #region ILocationService implementation

        public void initLocationService()
        {
            _googleApiClient.Connect ();
        }

        public Position getCurrentPosition ()
        {
            if (_googleApiClient.IsConnected) {
                _currentLocation = LocationServices.FusedLocationApi.GetLastLocation (_googleApiClient);
                _currentPosition = new Position (_currentLocation.Latitude, _currentLocation.Longitude);
            }

            _googleApiClient.Disconnect ();

            return new Position (_currentLocation.Latitude, _currentLocation.Longitude);
        }

        #endregion
        public void OnLocationChanged(Location l)
        {
            Console.WriteLine ("OnLocationChanged");
            _currentLocation = l;
        }

        public void OnConnectionFailed (ConnectionResult result)
        {
            Console.WriteLine ("ConnectionFailed");
        }

        #region IGoogleApiClientConnectionCallbacks implementation
        public void OnConnected (Android.OS.Bundle connectionHint)
        {
            Console.WriteLine ("OnConnected");

            if (!_googleApiClient.IsConnected)
                LocationServices.FusedLocationApi.RequestLocationUpdates (_googleApiClient, _locRequest, this);

            _currentLocation = LocationServices.FusedLocationApi.GetLastLocation (_googleApiClient);
        }
        public void OnConnectionSuspended (int cause)
        {
            Console.WriteLine ("OnConnectionSuspended");
        }
        #endregion
    }
}

在 nuMaps/Views/MapPage.xaml.cs 中的使用

using Xamarin.Forms;
using Xamarin.Forms.Maps;
using System;
using System.Diagnostics;

namespace nuMaps
{
    public partial class MapPage : ContentPage
    {

        public MapPage ()
        {
            InitializeComponent ();
            Position p = DependencyService.Get<ILocationService>().getCurrentPosition();
            MyMap.MoveToRegion (
                MapSpan.FromCenterAndRadius (
                    p, Distance.FromMiles (1)
                )
            );
        }
    }
}

nuMaps/Views/Loginpage.xaml.cs

using System;
using Xamarin.Forms;
using nuMaps;

namespace nuMaps
{
    public partial class LoginPage : ContentPage
    {
        public LoginPage ()
        {
            InitializeComponent ();

            /*
             * Init platform specific location service.
             * TODO: This *shouldn't* need to happen, but we don't get location information until
             * the OnConnected callback happens which is too slow to put in getCurrentLocation method.
             */

             DependencyService.Get<ILocationService>().initLocationService();
        }
    }
}

【问题讨论】:

标签: c# android ios mobile xamarin


【解决方案1】:

我相信问题在于您对ILocationService 的实现。

我将删除实施活动(为什么要使用 OnCreate?)并查看 http://developer.xamarin.com/guides/android/platform_features/maps_and_location/location/

我建议在 Android 上通过 google play api 获取 GPS 位置,这需要实现 ILocationListenerIGoogleApiClientConnectionCallbacksIGoogleApiClientOnConnectionFailedListener。希望对您有所帮助!

为 cmets 编辑:

如果问题中的 LocationService 是最新的,我看不到您正在实施 IGoogleApiClientConnectionCallbacksILocationListener。可能是因为地图页使用了 gps,GetLastKnownLocation 有效,因为最近获得了一个位置。

GPS 位置请求是一种异步操作 - IGoogleApiClientConnectionCallbacks 的方法之一是 OnConnected,您应该在其中调用类似:

LocationServices.FusedLocationApi.RequestLocationUpdates(googleApiClient, locationRequest, this);

这将主动请求位置更新,然后在返回位置更新时触发OnLocationChanged(Location location)。这都是异步的,因此您可能需要在 LocationService 中公开这些事件并订阅它们。

【讨论】:

  • 感谢您抽出宝贵时间回复!我测试了实现这些接口,但我似乎遇到了与实现 ILocationServer 相同的问题。他们似乎永远不会触发。我的 ILocationService::getCurrentPosition 被调用,但没有正确的上下文来获取设备的当前位置。
  • 嗯,你试过用 Forms.Context 作为上下文吗?
  • 我确实有一些运气将 Context 的上下文更改为 Application.Context 并删除了 Activity 实现。剩下的唯一问题是如何在第一次加载视图/地图时或在查看地图之前的应用程序生命周期中的任何其他时间正确获取位置。
  • 很高兴您能参与其中!您应该能够在应用程序生命周期中的任何时间调用该服务,因为 google play 位置服务不绑定到地图控件(除非我误解了您的问题)。
  • 在 MapPage.xaml.cs 中调用 getCurrentLocation 似乎会导致位置为空。我也尝试使用覆盖 OnAppearing(),但这也是 null。
【解决方案2】:

您可以尝试TinyIoC,而不是 Xamarin 依赖服务。它适用于特定于平台的实现,例如位置服务。

也许 Xamarin 依赖服务可用于这些类型的事情,但到目前为止我只将它用于自定义渲染器。对于更多基于服务的东西,我使用 TinyIoC。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-18
    • 2013-01-21
    • 2013-06-28
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    相关资源
    最近更新 更多