Android后台定位上传开发心得(仅经验,没有源代码)

来源:互联网 发布:手机怎么找淘宝客服 编辑:程序博客网 时间:2024/06/06 02:32
一、功能设计
app后台定位
app后台上传位置
定位和上传做在俩个单独的service里面,并配置到单独的进程里面
Activity只做前台显示和控制。不做具体功能,因此,Activity执行onPause之后,不影响后台定位和上传
支持关屏定位上传
二、手机定位
流量定位:
流量定位本来就不准,不准的原因是流量定位基于基站,只能定位到基站所在位置,跳来跳去是因为在基站信号边缘,
两个基站在来回切换,流量定位的误差值在300m-600m左右,现在基站的信号都比较强大,所以距离也比较远
WIFI定位:
根据ip定位,位置固定不变。
gps定位:
1.可用于实时定位位置,只能在室外
2.gps定位的原理与限制
gps的信号是广播式的,学名叫无源定位,就跟电台广播一样,发射的信号是精确的时间和卫星的位置信息。
我们手机和车上的gps模块也有精确时间。利用四颗卫星广播的信息进行定位。所以,并不是卫星针对某一个gps用户机发射信号,是无差别覆盖的。
GPS系统的接收机都是采用无源定位方式(就是接收机不需要发送信号)。
而我们手机没有大的接收天线,因此,在屋子里面收不到卫星的信号,不能定位。
3.注意:gps一个使用经验:其他应用可以正常使用gps,但是新通过Android Studio安装的应用偶尔不能使用gps,即便是打开了GPS开关,权限之类的。
处理办法是,重启手机,也就是说代码等是正确的,新安装了应用,不能定位,就重启一下手机即可。测试手机,魅族手机。
三、构架设计
在定位上传时候面对的环境:
1.网络未必稳定,不能保证请求成功(关流量,没有信号,欠费)
2.定位未必成功,遇到没有gps信号的地方
因此设计,俩个功能单独分开作为俩个单独的服务进程,分别做冗余设计。而俩个部分之间需要传输定位数据,而数据并不能保证一次性上传完成,
因此设计了单独的数据存储单元,作为定位服务和上传服务之间的桥梁和缓存。
这个桥梁选择的是sqlite数据库,同时Activity可以读取数据库里面的定位点,显示为轨迹。

整体结构如下:

                                           用于显示轨迹(只读消费者)
                                                                      ^
                                                                      |
        定位服务(生产者) -> 数据库(储存整条路径) -> 上传服务(读写消费者)

四、定位服务设计:
0.关于定位具体实现,参考高德官方示例工程代码
1.使用高德定位,使用连续定位,gps定位优先,高精度模式
2.定位监听器里面把定位到的数据加入到数据库里面
3.定位的结果有,gps定位,基站定位,WiFi定位,流量定位(基站定位)的定位结果是乱跳,形成杂乱的折线,根本不能用于记录轨迹,
因此,要记录轨迹,就只能使用GPS的定位。因此在定位结果里面屏蔽了基站定位的结果。(没有GPS信号,高德定位就会使用流量定位,重启定位的时候,第一个定位结果也是基站定位的类型)。
4.Activity开启服务之前,要检查定位权限和gps是否处于打开状态
5.GPS定位很费电,因此需要设计定位策略,不然太耗电影响使用体验。主要思想是调整定位频率,即在不移动的时候适当降低定位频率,检测到运动一定距离在恢复到常规定位频率
同时常规定位频率不可太高,(频率越高越费电,当然定位也越精确)步行记录轨迹建议6~10秒定位一次,汽车轨迹10~15秒一次
6.关闭屏幕时任然需要定位,因此需要使用wakelock。
五、上传服务设计
1.整体为一个大循环->从数据库读取一个或多个,调用http上传接口上传数据。
2.为了保证数据上传完整,必须建立确保机制:每个数据有一个标志上传成功的标志位在数据库里,如果上传成功则标记对应数据成功,不成功则不做处理,上传循环会依次读取未被发送的数据
因此,上传失败的数据下次还会被上传,直到上传成功。
3.为了省电,设计为批量上传,单次上传的话,数据包里面只有一个定位坐标,且上传次数多,又费流量又费电,因此设计为小批量上传
六、桥梁数据库设计
1.多线程访问sqlite数据库
根据功能设计,会有几个线程同时访问数据库的操作函数,而,sqlite不支持多线程读写。因此使用的时候会报错。解决的方法是给数据库操作函数加synchronized
比如:public synchronized List<PoiItem> read_poi( ) {
2.数据库设计为:id lat lng isuploaded 四列,id为自增的(lat,lng)为坐标,isuploaded是标记是否上传了的点
lat varchar(50) ,lng varchar(50) 位字符串类型长度50,定位坐标结果很长,需要50个字符长度
七、显示轨迹函数
使用高德提供的overlay函数,其他的关于高德地图的开发参考,高德地图官方示例工程代码

TraceOverlay mTraceOverlay = null;    //初始化调用一次    private void initOverlay() {        mTraceOverlay = new TraceOverlay(aMap);    }    //连续调用此函数,从而形成一条轨迹    private void overlayAdd(LatLng latLng) {        List<LatLng> list = new ArrayList<>();        list.add(latLng);        mTraceOverlay.add(list);        // mTraceOverlay.zoopToSpan();    }    //绘制完成清除轨迹    private void removeOverlay() {        if (mTraceOverlay != null) {            mTraceOverlay.remove();            mCurrentDbPos = 0;        }    aMap.clear();    }
八、定位函数参考高德官网示例,对于build.gradle官方文档没有及时更新,不能使用,应该使用以下

    compile 'com.amap.api:3dmap:5.4.0'                  //矢量地图    compile 'com.amap.api:search:latest.integration'    //收索反地理编码    compile 'com.amap.api:location:3.6.1'               //定位
九、Activity和service之间通信
对于,Activity给service发送消息而服务不必给Activity返回数据的情况,使用startService+intent来发送消息,startService可以多次调用,
对于,Activity和service需要互相发送数据的情况下,使用aidl这个专门设计用来他俩之间通信的工具。因为这个工具支持进程之间通信,而回调函数,messger不支持多进程
这里设计为,定位服务和上传服务分别在单独的进程,因此必须使用aidl
十、需要使用保活方案
在使用中,定位和长传俩个服务需要保持在后天运行,而Android自身和厂商都对后台应用做了限制,因此需要必要的保活机制,提高应用的等级而不被第一个杀掉,
同时需要一个被杀掉重启的功能。具体实现就不在这里讨论了。