站点图标 江湖人士

Xamarin.Android位置服务平台功能

Xamarin.Android位置服务平台功能

Xamarin.Android位置服务平台功能,本教程将介绍如何在Android应用中定位,以及如何利用Android Location Service API来获取用户位置,同时还会通过Google Location Services API的位置服务来处理定位。

概述

Android提供多种定位技术接口,如利用蜂窝塔、WiFi和GPS。针对每一个定位技术的细节都已经被抽象为 location providers ,这使得应用可以通过一致的方法来获取位置,而不用关心具体的服务实现。在本教程中,我们将介绍Android Location Service API,以及如何利用LocationManager来与系统位置服务进行通信。在教程的第二部分,我们会利用Google Location Services API —— 可用通过Google Play服务整合的定位功能来动态切换定位提供技术。

定位基础

在Android中,无论你使用什么API来获取定位数据,其中的基本概念是一致的。在本节中,我们将介绍位置提供程序和与位置相关的权限。

Xamarin.Android位置服务

有多种内置技术来精准定位用户位置。要用到哪些硬件取决于选择哪种类型的location provider来收集数据。Android中有以下三种位置提供程序:

位置提供程序并不是总是可用。例如,你可能需要在应用中使用GPS,但是GPS在设置中是关闭状态,或者设备没有GPS模块支持。如果特定的提供程序不可用,选择使用它会返回null值。

位置权限

一个定位应用需要访问设备的硬件传感器,以便于接收GPS,WiFi和蜂窝数据。访问权限由应用的Android Manifest控制。其中涉及到了两个权限 —— 这取决于你的应用要求和选择了哪个API,你可以申请其中一个权限:

在目标为API版本为21(Android 5.0 Lollipop)或者更高版本中,应用可以在没有GPS硬件模块的设备上使用ACCESS_FINE_LOCATION权限。如果你的应用需要GPS硬件,你需要在Android Manifest中明确添加android.hardware.location.gps uses-feature元素。更多信息见:uses-feature element

要设置权限,在解决方案管理器中,双击Properties,然后切换到Android Manifest标签。Required Permissions部分为权限列表:

注:图为官方文档内的图,上面的描述为Visual Studio操作描述。

Xamarin.Android位置服务

设置这些权限会告诉Android,你的应用需要访问那个定位技术的位置提供程序。

注意:设置了ACCESS_FINE_LOCATION意味着包括了两个定位数据权限。你不需要同时设置两个权限,仅仅为你的应用设置最少要求的权限。

使用Android Location Service获取位置信息

原文示例代码译文示例代码

Android位置服务是Android中使用位置信息的标准API。位置数据是由硬件传感器收集,并通过系统服务集中处理 —— 系统服务可以在应用中使用LocationManager类和ILocationListener来访问。

为了通过Android位置服务获取用户位置,我们需要以下操作:

  1. 添加对LocationManager类的引用
  2. 使用LocationManager向特定的服务程序请求位置更新
  3. 实现ILocationListener接口,并在其中处理位置改变事件。
  4. 当应用进入后台时,停止位置更新。

位置服务

位置服务是系统中服务管理的一种特殊类型。系统服务和硬件设备交互,并一直保持运行。要在 我们的应用中使用位置更新,我们需要利用LocationManager和RequestLocationUpdates调用向系统位置服务请求位置更新。

位置管理

我们可以通过LocationManager类实例来访问系统位置服务。LocationManager是一个特殊的类,它用于和系统位置服务交互,并通过它调用方法。应用可以通过调用GetSystemService来引用LocationManager,同时需要传入一个服务类型,示例如下:

LocationManager locMgr;
...
locMgr = GetSystemService (Context.LocationService) as LocationManager;

OnCreate中比较适合创建LocationManager引用。将LocationManager定义为类的变量会比较好,这样在Activity的生命周期中的各个点都可以调用它。

请求位置更新

一旦我们的应用创建了LocationManager引用,我们就需要告诉LocationManager我们需要什么类型的位置信息,以及我们要多久更新一次。我们可以通过调用LocationManager类对象的RequestionLocationUpdates方法(同时需要传递更新条件)来更新位置信息。

RequestionLocationUpdates方法告诉系统位置服务,你的应用需要开始接收位置更新。此方法语句你指定提供程序,以及控制更新频率的时间和距离阈值。例如,如下代码,要求每2000毫秒请求一次位置更新,并且只有当位置更改超过1米时才更新:

protected override void OnResume ()
{
    base.OnResume ();
    string Provider = LocationManager.GpsProvider;

    if(locMgr.IsProviderEnabled(Provider))
    {
    locMgr.RequestLocationUpdates (Provider, 2000, 1, this);
    }
    else
    {
    Log.Info(tag, Provider + " is not available. Does the device have location services enabled?");
    }
}

应用程序应该按照需要控制执行请求位置更新。这可以延长电池寿命,同时为用户提供更好的体验。

订阅位置更新

一旦应用通过LocationManager请求了位置更新,它可以通过实现ILocationListener接口来接受服务提供的信息。此接口提供监控位置服务和位置提供程序的方法。

以下代码示例为在MainActivity中实现ILocationListener:

public class MainActivity : Activity, ILocationListener
{
    ...

    public void OnProviderEnabled (string provider)
    {
        ...
    }
    public void OnProviderDisabled (string provider)
    {
        ...
    }
    public void OnStatusChanged (string provider, Availability status, Bundle extras)
    {
        ...
    }
    public void OnLocationChanged (Android.Locations.Location location)
    {
        ...
    }
}

此接口让我们可以订阅四个系统事件,以供检测提供程序状态和获取位置信息:

以下代码示例说明了Activity应该如何实现OnLocationChanged方法来接收位置更新,并将其显示到界面:

TextView latitude;
TextView longitude;

public void OnLocationChanged (Location location)
{
latitude.Text = "Latitude: " + location.Latitude;
longitude.Text = "Longitude: " + location.Longitude;
}

停止位置更新

RemoveUpdates方法告诉系统位置服务停止发送更新数据到我们的应用。在OnPause中调用此方法,当应用的Activity不在前台显示时,应用移除位置更新可以节省电量:

protected override void OnPause ()
{
base.OnPause ();
locMgr.RemoveUpdates (this);
}

如果你的应用需要在后台仍可已获取位置更新,你需要创建一个定制服务来订阅系统位置服务。关于后台服务的信息见:原文:Backgrounding with Android Services

获取最好的提供程序

上述示例使用GPS作为位置提供程序。但是,GPS并不是所有情况下都可用,例如,设备处于室内或设备没有GPS接收器。如果是这种情况,我们会从提供程序获得null值。

如果我们想要我们的应用在GPS不可用的情况下工作,我们可以应用启动时使用GetBestProvider方法获取最好且可用(设备支持且用户启用)的位置提供程序。我们可以通过告诉GetBestProvider方法我们的提供程序要求来取代直接传递指定的提供程序。例如:传入精度和耗电要求 —— 使用Criteria对象,这样GetBestProvider会通过给定的Criteria来返回最适合的提供程序。

以下代码展示了如何获得最合适的提供程序,以及在请求位置更新时,如何使用它:

Criteria locationCriteria = new Criteria();

locationCriteria.Accuracy = Accuracy.Coarse;
locationCriteria.PowerRequirement = Power.Medium;

locationProvider = locMgr.GetBestProvider(locationCriteria, true);

if(locationProvider != null)
{
    locMgr.RequestLocationUpdates (locationProvider, 2000, 1, this);
}
else
{
    Log.Info(tag, "No location providers available");
}

注意:如果用户禁用了所有位置提供程序,GetBestProvider将会返回null值。

为了展示代码如何在真实设备上工作,请确保GPS,WiFi和蜂窝网络启用。可以如截图显示设置:Google设置——位置——模式

如下截图演示了利用GetBestProvider获取位置的位置应用:

请记住,GetBestProvider不会动态更新提供程序。相反,它在Activity的生命周期中只确定一次最佳提供程序。如果在已经获取过提供程序后,提供程序状态发生了变化,应用则需要为ILocationListener中的方法(OnProviderEnabled, OnProviderDisabled, 和 OnStatusChanged)添加额外的代码来处理提供程序的切换。

为了使常见场景变得简单,以及使用较少的代码,Google为我们引入了FusedLocationProvider来处理提供程序的改变。FusedLocationProvider是Google位置服务API的一部分,Google位置服务是附加在Google Play服务上的。我们将在下面介绍它。

通过Google位置服务和FusedLocationProvide获取位置

由于国内大部分厂商提供的Android机都没有Google服务,故此处暂不做翻译。
原文见:Get Location with Google Location Services and the Fused Location Provider
原文示例代码

退出移动版