位置

要在 Android 中构建位置感知应用,有两种途径:

LocationManager

优点

  • 更精细的控制
  • 适用于所有设备
  • Android 框架的一部分

缺点

  • 如果管理不当,电池耗尽是一个问题
  • 如果设备无法找到位置(例如建筑物内的 GPS 不良),则需要逻辑来切换位置提供商

特征

  • NMEA 听众
  • GPS 状态监听器
  • 收听提供商状态更改(例如,用户关闭 GPS)
  • 从中选择位置源的提供商列表

供应商

全球定位系统

  • 所需权限:
  • 准确度:10 米 - 100 米
  • 电源要求:HIGH
  • 可用性:全球(能够清晰地看到天空)
  • 注意
    • 位置更新通常每秒进行一次,但是在 GPS 已经使用一段时间并且 A-GPS 不可用的情况下,接收位置需要几分钟。
    • 在天空的清晰视野被阻挡的情况下,由于“ 城市峡谷 ”效应,GPS 点将不会非常好地聚集(位置点跳跃)并且在某些区域中准确性可能会误导。

网络

  • 所需权限:
  • 准确度:100m - 1000m +
  • 电源要求:低 - 中等
  • 可用性:在蜂窝塔或 wifi 信号范围内
  • 笔记:
    • 位置更新发生频率低于 GPS
    • 位置更新通常不能很好地聚类(位置点跳跃),并且准确度可以取决于不同因素的数量(wifi 信号的数量,信号强度,蜂窝塔的类型等)。

被动

  • 所需权限:
  • 准确度:10 米 - 1000 米+
  • 电源要求:无
  • 可用性:仅当另一个应用程序从 GPS 或网络接收位置时
  • 笔记:
    • 不要依赖它来为你提供持续更新。这会被动地侦听到发出位置请求的其他应用程序,并将这些位置传回。
    • 不返回 FusedLocationProviderApi 生成的点,仅返回用于生成它们的基础位置点。

FusedLocationProviderApi

优点

  • 提供更少的电池消耗开箱即用
  • 处理好 GPS 很好
  • 更频繁地获取更新

缺点

  • 对颗粒的控制较少
  • 可能无法在所有设备或某些国家/地区使用
  • 需要第三方库依赖

特征

  • 妥善管理使用位置提供商以节省最佳电池
  • 通常会生成比网络位置提供商更准确的点
  • 更频繁地更新库,允许更多改进
  • 无需指定要使用的提供程序类型

LocationRequest 优先级

PRIORITY_HIGH_ACCURACY

  • 所需权限:
  • 准确度:10 米 - 100 米
  • 电源要求:HIGH
  • 可用性:Google Play 服务的可用位置。
  • 笔记:
    • 如果未使用 ACCESS_FINE_LOCATION ,则不会使用 GPS 生成位置更新,但仍会在正确的条件下找到相当准确的点。
    • 如果使用 ACCESS_FINE_LOCATION ,它可能会或可能不会使用 GPS 来生成位置点,具体取决于在给定环境条件下它当前可以跟踪设备的准确度。
    • 虽然这可能比其他设置报告更准确的位置更新,但它仍然倾向于“ 城市峡谷 ”效应。

PRIORITY_BALANCED_POWER_ACCURACY

  • 所需权限:
  • 准确度:100m - 1000m +
  • 电源要求:MEDIUM
  • 可用性:Google Play 服务的可用位置。
  • 笔记:
    • PRIORITY_HIGH_ACCURACY 相同的音符
    • 虽然不太可能,但此设置仍可能使用 GPS 生成位置。

PRIORITY_LOW_POWER

  • 所需权限:
  • 准确度:100m - 1000m +
  • 电源要求:低
  • 可用性:Google Play 服务的可用位置。
  • 笔记:
    • 可能不使用 GPS,但到目前为止尚未经过测试。
    • 更新通常不是很准确
    • 通常用于检测位置的重大变化

PRIORITY_NO_POWER

  • 所需权限:
  • 准确度:10 米 - 1000 米+
  • 电源要求:无
  • 可用性:Google Play 服务的可用位置。
  • 笔记:
    • 功能几乎与 LocationManager PASSIVE_PROVIDER 相同
    • 收到时报告 Google Play 服务更新,其中 PASSIVE_PROVIDER 报告使用的基础位置更新

故障排除

OnLocationChanged() 从不调用

由于这似乎是获取 Android Locations 的常见问题,因此我将简要列出常见修复程序:

  1. 检查你的清单!

    最常见的问题之一是从未给出正确的权限。如果你使用 GPS(有或没有网络),请使用 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>,否则使用 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>。谷歌的 FusedLocationApi 需要 ACCESS_FINE_LOCATION

  2. (适用于 Android 6+) 检查运行时权限

    检查并请求权限! 如果你从未获得权限,你最终会崩溃,或者更糟(如果你正在捕捉所有例外情况),你最终都没有任何迹象! 如果用户在应用程序启动时授予你权限并不重要,请始终检查你是否拥有所有呼叫的权限。用户可以轻松地进入他们的设置并撤消它们。

  3. 仔细检查你的代码!

    你确定你是在传递正确的倾听者吗?你把 BroadcastReceiverIntentService 添加到你的清单中了吗?你是在 BroadcastReceiver 级上使用 PendingIntent.getService(),还是在 IntentService 级上使用 getBroadcast()?你确定在请求后立即在代码中的其他位置取消注册你的侦听器吗?

  4. 检查设备设置!

    显然,请确保你已启用位置服务。

    https://i.stack.imgur.com/XDsXs.jpg

    如果你使用网络服务,是否打开扫描始终可用?你的位置模式是否设置为最佳高精度)或省电仅网络)?

    https://i.stack.imgur.com/IJpXQ.jpg

    如果你使用 GPS,你是否在位置模式下打开最佳高精度)或仅设备

    https://i.stack.imgur.com/wgBuU.jpg

  5. 仔细检查你的代码!

    是的,这是两次。你是否尝试使用 LocationListener 而不是 PendingIntent,反之亦然,以确保你实际正确实施了 LocationManager?你确定在你预期不会发生的活动或服务生命周期的某些部分中未删除位置请求吗?

  6. 检查周围的环境!

    你在旧金山市中心一栋楼的一楼测试 GPS 吗?你是否在不知名的地方测试网络位置?你是否在一个没有所有无线电信号的秘密地下掩体中工作,想知道为什么你的设备没有位置?在尝试解决位置问题时,请务必仔细检查周围环境!

可能有许多其他不太明显的原因,为什么位置不起作用,但在搜索那些深奥的修复之前,只需运行这个快速清单。