1.概述

去年自己参与了一款含有GIS核心功能的App开发,开发结束后自己在笔记软件做了项目总结,今天特意想起来,就将其搬到博客这里来,并进行一定的修改优化。庆幸自己一直有做完项目即时做总结的习惯,否则此时再去回顾,多半无从下手。

此款软件,为了降低开发成本,我们采用了跨平台的React-Native框架。App主体功能有两个:GIS功能和表单功能。其中,GIS功能包括地图展示、图例绘制、地点搜索、地点导航、轨迹搜集等;表格功能即是信息展示、信息填写、信息上传等一般表单包含的功能。虽然说自己也参与部分表单功能的开发(比如区域选择器、表单内容约束机制等),但GIS功能主要由我负责,自己对这块体会更加深刻,因此,本文主要介绍移动端GIS功能开发,包括使用的框架、核心包\组件、遇到的问题及解决方法等。

gis ios 移动开发 移动gis与app开发_gis ios 移动开发

2.框架及核心库

App采用跨平台的React-Native框架,而地图页面是H5页面,GIS库采用Leaflet
1. 上述框架确定前的技术预研及踩坑:
A、在GIS库方面,我在Leaflet、OpenLayers、MapboxGL三款基础地图库中,根据稳定性、软件成熟度、社区生态链完善程度几项指标,选择了Leaflet作为基础地图库,后续开发证明选择确实没错,“Leaflet包含了大量第三方插件,需要什么功能,都可以先到Github上搜索,常见的功能都有对应的第三方库实现了。同时,Leaflet文档也相当完善及高质量。”
B、在决定采用H5页面开发方面,前期自己先检索了React-Native的第三方地图包,结果都没有找到合适的,例如react-native-maps需要用到谷歌地图,因此不适合国内。最后才确定在react-native中嵌入H5页面,而H5页面用一个新项目实现,用webpack打包工具打包。
2. 使用到的核心库/组件:

  • react-native-webview: 用于在React-Native项目中嵌入H5页面。
  • react-native-loaction: 用于获取手机当前位置。
  • react-native-foreground-service: 用于安卓手机开启前台任务。
  • HtmlWebpackInlineSourcePlugin: 用于将引用到js文件及css文件都打包进html文件中。
  • 天地图: 提供地图源服务及搜索服务。
  • 腾讯地图/高德地图/百度地图: 提供跳转到App进行导航的api。

3.问题及解决方法(需求及实现方式)

1.H5页面路径: 由于在android上,传给react-native-webview包source参数的值需要是绝对路径(‘file:///android_asset/pages/index.html’),而在ios上,传入的值可以是相对路径,因此需要将H5页面引用到的js文件、css文件都复制到android/app/src/asset目录下以及另外一个路径(用于ios)。
2.调试H5页面: react-native-webview调试需要用到Chrome Inspect工具调试前,需要将地图页面项目webpack配置中的HtmlWebpackInlineSourcePlugin插件去掉,否则无法定位问题至具体的js文件。
3.react-native-webview与H5页面通信: 在H5页面上,android页面需要通过document.addEventListener() 监听RN发送过来的消息,而ios平台则是通过window.addEventListener()。为了在页面初始化前能获知平台类型,需要通过react-native-webview的injectedJavaScriptBeforeContentLoaded属性传入字符串赋值。
4.实时获取手机当前位置:

  • 定位功能:首先,尝试使用Leaflet地图库的api及Html5的api,两者都可以实现,Leaflet的api实际上是在Html5的api做了封装而已,但在适配ios时出现了位置权限提示的问题(弹窗提示"xx/xx/index.html想使用您当前位置"),而且在外边的react-native已经请求过权限了,因此重新找了react-native-location包实现定位功能。
  • 轨迹搜集功能:首先,因为react-native-locationgetLatestLocation() api经常返回过时的位置,因此没办法用 “定时调用该api来实现轨迹搜集” ;接着,由于配置不对,所以react-native-locationsubscribeToLocationUpdates api不能及时更新位置;最后,修改了 "
    interval;maxWaitTime"
    这两个参数实现实时获取用户位置的功能。
  • 后台运行轨迹搜集:首先,由于expo包有后台获取位置的api,所以先尝试用expo的api去获取位置,但发现始终没返回,猜测是GooglePlay的原因,但没能验证,所以也没有放弃;然后,尝试通过expoBackgroundFetch api定时调用其它包的位置获取api来实现功能,但间隔时间最短没有少于1min,无法实现功能需求;接着,尝试使用之前的定位功能时会报 “你的设备不支持GooglePlay,因此无法运行xxx” 的问题,最终调试是expo-location包的原因,因此得出expo包获取位置是需要谷歌服务的,因此放弃expo方案;最后,由间隔时间最短限制查到android文档上说明了android8+以上会对后台应用做程序运行频率进行限制,同时看到了成为前台应用的几个条件,其中一个是有前台任务,因此去github找前台任务的react-native包,最终找到了react-native-foreground-service,至此,完成了安卓后台运行轨迹搜集功能;而针对ios平台,则是看到了react-native-location包中有一个设置 “allowsBackgroundLocationUpdates”,最终开启这个设置便实现了后台运行。

4.总结

经验证,移动端GIS功能开发可以采用如下框架及技术:
1.采用React-Native作为App主体框架,地图页面作为一个单独项目,最终打包成H5页面,用react-native-webview组件加载H5页面。
2.地图页面采用Leaflet基础地图库,地图源使用天地图(免费),天地图同时也提供POI搜索、路线规划等GIS服务。
3.地图页面页面上:图例展示、绘制、点击等由Leaflet实现;POI搜索由天地图服务提供,地点导航由高德地图、腾讯地图、百度地图提供api跳转实现;定位功能及轨迹搜集功能借助react-native-loaction实现。
整体来说,采用全部免费的框架及技术实现,难度会比直接使用收费的地图库大很多,而且实现效果也完全比不上,比如说用 react-native-loaction 第三方库实现的轨迹搜集功能,会存在GPS漂移、轨迹路线不顺滑等问题,如果想进一步优化,可以采用卡尔曼滤波优化,这种优化有检索过,没有实现过。总之,收费的才是最好的(@_@)。