给Traccar定位软件的安卓客户端 新增Fused Provider
我一直有在使用手机GPS定位工具,方便记录行踪。Traccar是一个不错的开源软件,有安卓和iOS客户端,可以自建服务器,客户端只会把定位数据上传到自建的服务器,不担心数据隐私问题,另外服务器也自带一个Web界面可以管理和查看设备的历史位置信息。
现有定位的不足
定位精度有高中低三个选项,但实测都不太好用。选择高精度非常费电,而且只在室外有效,在室内收不到位置更新。选择中精度不费电了,但定位不准确。选择低精度经常不更新位置信息。
查看Traccar源代码https://github.com/traccar/traccar-client-android ,定位能力是基于安卓原生的LocationManager,高精度是用GPS_PROVIDER,只会从GPS传感器获取定位,费电之余室内完全无法使用,中精度是用NETWORK_PROVIDER,通过蜂窝网络、基站、Wifi等信息定位,不太费电但精度不高。低精度是用PASSIVE_PROVIDER,被动获取定位,不会主动获取定位,所以需要有其他App主动获取定位,OS才会把位置信息顺便也提供到给Traccar,比较随缘。
引入FUSED_PROVIDER
安卓API 31版本后(安卓12或以上)其实有个更先进的provider可供使用,FUSED_PROVIDER,系统会自动从GPS、蜂窝网络、Wifi等多种模块或传感器计算,直接给出一个平衡耗电量以及精度的位置,而不需要自己管理。在此之前如果要实现比较智能地获取位置,需要自己写策略,平衡精度和耗电量,在不同条件下使用不同的provider,然后自己整合各方数据和精度计算得出位置信息。

Traccar安卓客户端二次开发
于是开始对Traccar源码v7.7版本进行二次开发,添加FUSED_PROVIDER选项。 先是添加LocationManager.FUSED_PROVIDER的可选值,如果选中,启动服务运行requestLocationUpdates()时带入。另外顺便添加了日志,打印设备支持的所有providers以及当前可用的providers列表,方便查看。例如用户关闭了手机的GPS功能,那么所有providers列表里也会出现GPS_PROVIDER,但是不会出现在当前可用的providers列表里。

然后在App的设置选单里也添加Fused选项,另外也把服务器URL预设值从traccar的demo服务器地址改成了我自建的服务器地址。

对更新间隔也做了一个小优化,当distance>0或angle>0时,requestLocationUpdates()会传入用户设置的interval值(参考上面AndroidPositionProvider.kt的第38行),OS给App回调函数提供位置信息不会短于这个时间间隔,因此App在processLocation()处理接收到的位置更新时直接处理即可,不需要再判断是否满足interval时间间隔,因此添加了一个条件distance<=0和angle<=0时直接处理(与上面的distance>0或angle>0相反)

最后为了严谨,需要更新一下gradle的build script,里面最低SDK版本改成31。

使用效果
编译后在手机上使用的效果图,App标题也从Traccar Client成了自己的项目名称DH Boardcast

连续运作一周,效果比之前大幅改善,在耗电不高的情况下,能维持稳定的位置更新和不错的精度。
2025.06更新
原作者后来迁移到了新框架,统一用Flutter来实现客户端,原来的android和iOS原生版本停止维护。实测新版本,感觉没有之前的原生版本好用,另外在新框架里发现一个位置更新的参数问题,提了一个Issue建议 ,后来优化了。不过接下来还是继续沿用原生版本。