背景
3月30日openharmony3.1版本发布,openharmony新增许多服务功能组件,具体新添加的功能可以通过社区获取,当然新增组件中包含位置服务组件,用于位置相关的服务功能如定位,导航等等。本文通过详细代码具体分析其数据流程。
注意:代码分析需要一定c/c++代码阅读知识,当然由于代码为个人理解和社区代码不完的原因,会存在理解上面的偏差。
location介绍
仓库位置
location仓库位于base目录下面,其具体位置如图:
location 简介说明
位置能力用于确定用户设备在哪里,系统使用位置坐标标示设备的位置,并用多种定位技术提供服务,如GNSS定位、基站定位、WLAN/蓝牙定位(基站定位、WLAN/蓝牙定位后续统称“网络定位技术”)。通过这些定位技术,无论用户设备在室内或是户外,都可以准确地确定设备位置。
坐标
系统以1984年世界大地坐标系统为参考,使用经度、纬度数据描述地球上的一个位置。
GNSS定位
基于全球导航系统,包含:GPS、GLONASS、北斗、Galileo等,通过导航,设备芯片提供的定位算法,来确定设备准确位置。定位过程具体使用哪些定位系统,取决于用户设备的硬件能力。
基站定位
根据设备当前驻网基站和相邻基站的位置,估算设备当前位置。此定位方式的定位结果精度相对较低,并且需要设备可以访问蜂窝网络。
WLAN、蓝牙定位
根据设备可搜索到的周围WLAN、蓝牙设备位置,估算设备当前位置。此定位方式的定位结果精度依赖设备周围可见的固定WLAN、蓝牙设备的分布,密度较高时,精度也相较与基站定位方式更高,同时也需要设备可以访问网络。
框架介绍
说明:代码验证使用开发板为RK3568开发板。代码为主线4月8日代码。应用开发deveco studio API we为9版本,应用采用ets语言开发。
应用开发
使用deveco 编写一个简单的应用。通应用(即使用js)调用对应位置服务打开对应的接口。
应用代码如下:
tring = ''
private isWlanEnable: boolean = false;
private islocationon: boolean = false;
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Toggle({ type: ToggleType.Switch, isOn: this.isWlanEnable })
.width(50)
.height(40)
.onChange((isOn: boolean) => {
this.isWlanEnable = !this.isWlanEnable;
if (this.isWlanEnable) {
this.islocationon = true;
this.switchOn();
}
})
Text("地址" + this.text)
.fontSize(50)
}
.width('100%')
}
.height('100%')
}
private switchOn() {
//导航场景
var requestInfo = {'scenario': 0x301, 'timeInterval': 0, 'distanceInterval': 0, 'maxAccuracy': 0};
//精度优先的
//var requestInfo = {'priority': 0x201, 'timeInterval': 0, 'distanceInterval': 10, 'maxAccuracy': 10};
var locationChange = (location) => {
console.log('locationChanger: data: ' + JSON.stringify(location));
};
// 打开位置信息
geolocation.on('locationChange', requestInfo, locationChange);
// 位置信息转换
var reverseGeocodeRequest = {"latitude": 31.12, "longitude": 121.11, "maxItems": 1};
geolocation.getAddressesFromLocation(reverseGeocodeRequest, (data) => {
console.log('getAddressesFromLocation address: ' + JSON.stringify(data));
this.text = data;
});
}
}
应用截图:
代码数据流程
开发板通过配置连接wifi,并打开位置信息(设置->隐私->位置),运行编译安装好的应用,通过hilog收集开发板中对应日志信息。我们可以逐步了解数据流转过程。注意:由于当前位置的使用没有具体的指导手册,位置授权处理是通过对CheckLocationPermission函数进行修改(应用中配置main_pages.json配置权限未见起作用)。
修改如下:
通过hilog 获取日志。我们可以收集部分location 对应的信息。通过02300标识筛选与位置相关的日志信息。日志信息如图(当前图片日志信息已经在代码中增添一部分,非代码原始日志):
位置流程框架
当开启应用时,从APP到底层的流程如下:
On(napi_env env, napi_callback_info cbinfo) 函数为拉起位置服务相关功能入口函数。
On函数实现机制
napi_value On(napi_env env, napi_callback_info cbinfo)
cbinfo 信息为js传入信息参数信息,具体实现过程可以分析相关代码。
on 函数中实现类型有以下几种:
1、locationServiceState。
2、gnssStatusChange。
3、nmeaMessageChange。
4、cachedGnssLocationsReporting。
5、fenceStat。
6、locationChange。
当前暂时不清楚其他几种类型的使用方法。需要后期研究。当前使用的为locationChange类型。
通过locationChange(APP配置)进入到SubscribeLocationChange。其中SubscribeLocationChange 中JsObjToLocationRequest将相关配置信息转换保存到对应的配置文件中。注意JsObjToLocationRequest由于JsObjectToInt没有对返回值进行判断,这里存在一个BUG。不存在的参数会将上一个参数的值传递到下一个变量。参考issue
g_locatorNapiPtr->StartLocating(requestConfig, locatorCallback); 拉起定位。
StartLocating
int LocatorAbility::StartLocating(std::unique_ptr<RequestConfig>& requestConfig, sptr<ILocatorCallback>& callback, std::string bundleName, pid_t pid, pid_t uid)
进行对应的ability配置:
ProxySendLocationRequest
ProxySendLocationRequest 函数中,对应的使用3种类型的能力GNSS_ABILITY、NETWORK_ABILITY、PASSIVE_ABILITY。
由日志分析detect passive/gps/network ability requests(size:0) work record:[]这3种ability 的size为0,暂不清楚这种影响。
行 28932: 04-18 16:56:52.132 368 368 I 02300/RequestManager: RequestManager::HandleStartLocating
行 28934: 04-18 16:56:52.132 368 368 D 02300/Locator: RequestConfig::ToString
行 28941: 04-18 16:56:52.132 368 368 I 02300/RequestManager: RestorRequest add request:[request config: scenario : 513, location priority : 513, timeInterval : 0, distanceInterval : 0, maxAccuracy : 0, fixNumber : 0] from pid:1891, uid:20010033, location.ILocator, callback's address : 0x1d80390
行 28943: 04-18 16:56:52.132 368 368 D 02300/RequestManager: add new receiver with new callback
行 28945: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager::UpdateRequestRecord1
行 28948: 04-18 16:56:52.132 368 368 E 02300/RequestManager: can not get proxy name according to request configuration
行 28950: 04-18 16:56:52.132 368 368 E 02300/RequestManager: RequestManager::HandleRequest
行 28952: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager ProxySendLocationRequest
行 28955: 04-18 16:56:52.132 368 368 D 02300/RequestManager: detect gps ability requests(size:0) work record:[]
行 28957: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager GetRemoteObject
行 28960: 04-18 16:56:52.132 368 368 I 02300/GnssAbility: GnssAbilityStub OnRemoteRequest cmd = 1, flags= 0, pid= 368, uid= 0
行 28962: 04-18 16:56:52.132 368 368 I 02300/GnssAbility: refrash requirements
行 28965: 04-18 16:56:52.132 368 368 D 02300/GnssAbility: RemoteRequest Transact ErrCode = 0
行 28968: 04-18 16:56:52.132 368 368 I 02300/FusionController: fused flag:0
行 28971: 04-18 16:56:52.132 368 368 I 02300/NetworkAbility: NetworkAbilityStub OnRemoteRequest cmd = 4, flags= 0, pid= 368, uid= 0
行 28973: 04-18 16:56:52.132 368 368 E 02300/NetworkAbility: SelfRequest 0
行 28976: 04-18 16:56:52.132 368 368 I 02300/NetworkAbility: refrash requirements
行 28978: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager ProxySendLocationRequest
行 28980: 04-18 16:56:52.132 368 368 D 02300/RequestManager: detect network ability requests(size:0) work record:[]
行 28982: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager GetRemoteObject
行 28985: 04-18 16:56:52.132 368 368 I 02300/NetworkAbility: NetworkAbilityStub OnRemoteRequest cmd = 1, flags= 0, pid= 368, uid= 0
行 28987: 04-18 16:56:52.132 368 368 I 02300/NetworkAbility: refrash requirements
行 28989: 04-18 16:56:52.132 368 368 D 02300/NetworkAbility: RemoteRequest Transact ErrCode = 0
行 28992: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager ProxySendLocationRequest
行 28994: 04-18 16:56:52.132 368 368 D 02300/RequestManager: detect passive ability requests(size:0) work record:[]
行 28996: 04-18 16:56:52.132 368 368 D 02300/RequestManager: RequestManager GetRemoteObject
行 28999: 04-18 16:56:52.132 368 368 I 02300/PassiveAbility: PassiveAbilityStub OnRemoteRequest cmd = 1, flags= 0, pid= 368, uid= 0
行 29002: 04-18 16:56:52.132 368 368 I 02300/PassiveAbility: refrash requirements
行 29004: 04-18 16:56:52.132 368 368 D 02300/PassiveAbility: RemoteRequest Transact ErrCode = 0
行 29010: 04-18 16:56:52.133 368 368 D 02300/LocatorCallback: OnLocatingStatusChange Transact ErrCode
结束
location on 函数分析流程到此结束其中只是简单的分析了locationChange 类型的流程,其余locationServiceState/gnssStatusChange/nmeaMessageChange/cachedGnssLocationsReporting/fenceStatusChange有具体使用方法时在一一进行分析。