定位模块之getAddressesFromLocation函数解析 原创 精华
::: hljs-center
定位模块之getAddressesFromLocation函数解析
:::
@[toc](目录
-
-
背景
-
GetAddressesFromLocation 通过当前相对坐标获取地址名称。由于不清楚当前版本配置,目前暂时未能通过经纬度获坐标获取到地址名称,以下内容为数据流程分析。参考社区提供相关信息通过应用使用经纬度获取相地址名称,其中应用配置参考on函数分析。
-
-
定位功能函数
-
location_napi_entry.cpp init函数中已经配置好js与C++转换函数,当然也可以参考@ohos.geolocation.d.ts文件的函数。即定位模组需要使用的函数。
static napi_value Init(napi_env env, napi_value exports)
{
LBSLOGI(LOCATION_NAPI, "Init,location_napi_entry");
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("getLastLocation", GetLastLocation),
DECLARE_NAPI_FUNCTION("isLocationEnabled", IsLocationEnabled),
DECLARE_NAPI_FUNCTION("requestEnableLocation", RequestEnableLocation),
DECLARE_NAPI_FUNCTION("enableLocation", EnableLocation),
DECLARE_NAPI_FUNCTION("disableLocation", DisableLocation),
DECLARE_NAPI_FUNCTION("getAddressesFromLocation", GetAddressesFromLocation),
DECLARE_NAPI_FUNCTION("getAddressesFromLocationName", GetAddressesFromLocationName),
DECLARE_NAPI_FUNCTION("isGeoServiceAvailable", IsGeoServiceAvailable),
DECLARE_NAPI_FUNCTION("isLocationPrivacyConfirmed", IsLocationPrivacyConfirmed),
DECLARE_NAPI_FUNCTION("setLocationPrivacyConfirmStatus", SetLocationPrivacyConfirmStatus),
DECLARE_NAPI_FUNCTION("getCachedGnssLocationsSize", GetCachedGnssLocationsSize),
DECLARE_NAPI_FUNCTION("flushCachedGnssLocations", FlushCachedGnssLocations),
DECLARE_NAPI_FUNCTION("sendCommand", SendCommand),
DECLARE_NAPI_FUNCTION("on", On),
DECLARE_NAPI_FUNCTION("off", Off),
DECLARE_NAPI_FUNCTION("getCurrentLocation", GetCurrentLocation),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
return exports;
}
-
-
GetAddressesFromLocation
-
GetAddressesFromLocation 函数实现体如下,JsObjToReverseGeoCodeRequest函数将对应的经纬度写入到asyncContext->reverseGeoCodeRequest。
napi_value GetAddressesFromLocation(napi_env env, napi_callback_info info)
{
size_t argc = 2;
napi_value argv[argc];
napi_value thisVar = nullptr;
void* data = nullptr;
LBSLOGI(LOCATOR_STANDARD, "GetAddressesFromLocation");
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorPtr != nullptr, "locator instance is null.");
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
napi_valuetype valueType;
napi_typeof(env, argv[0], &valueType);
NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object is expected for parameter 1.");
ReverseGeoCodeAsyncContext* asyncContext = new (std::nothrow) ReverseGeoCodeAsyncContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
napi_create_string_latin1(env, "getAddressesFromLocation", NAPI_AUTO_LENGTH, &asyncContext->resourceName);
JsObjToReverseGeoCodeRequest(env, argv[0], asyncContext->reverseGeoCodeRequest);
asyncContext->executeFunc = [&](void* data) -> void {
ReverseGeoCodeAsyncContext* context = static_cast<ReverseGeoCodeAsyncContext*>(data);
if (g_locatorPtr->IsLocationEnabled()) {
g_locatorPtr->GetAddressByCoordinate(context->reverseGeoCodeRequest, context->replyList);
}
if (context->replyList.empty()) {
context->errCode = REVERSE_GEOCODE_ERROR;
} else {
context->errCode = SUCCESS;
}
LBSLOGI(LOCATOR_STANDARD, "Push executeFunc replyList is %{public}u", context->errCode);
};
asyncContext->completeFunc = [&](void* data) -> void {
ReverseGeoCodeAsyncContext* context = static_cast<ReverseGeoCodeAsyncContext*>(data);
napi_create_array_with_length(context->env, context->replyList.size(), &context->result[PARAM1]);
GeoAddressesToJsObj(context->env, context->replyList, context->result[PARAM1]);
LBSLOGI(LOCATOR_STANDARD, "Push GetAddressesFromLocation result to client");
};
size_t nonCallbackArgNum = 1;
return DoAsyncWork(env, asyncContext, argc, argv, nonCallbackArgNum);
}
其中使用lamba语言对发送(asyncContext->executeFunc)和 结果asyncContext->completeFunc进行组合。
执行体:
g_locatorPtr->IsLocationEnabled() 用于检验是否具有定位功能,需要打开定位功能即设置->隐私->定位服务
g_locatorPtr->GetAddressByCoordinate 获取地址函数
-
-
消息收发
-
行 27334: 04-19 14:55:55.416 1878 1918 E 02300/Locator_standard: context->executeFunc
行 27335: 04-19 14:55:55.417 374 1003 I 02300/Locator: OnReceived3 cmd = 1, flags= 0, pid= 1878, uid= 20010033
行 27336: 04-19 14:55:55.417 374 1003 D 02300/LocationNapi: IsExistFile = 1
行 27337: 04-19 14:55:55.417 1878 1918 D 02300/Locator_standard: Proxy::GetSwitchState Transact ErrCode = 0
行 27338: 04-19 14:55:55.417 1878 1918 D 02300/Locator_standard: Proxy::GetSwitchState return 1
行 27339: 04-19 14:55:55.417 1878 1918 D 02300/Locator_standard: Proxy::GetAddressByCoordinate1
行 27340: 04-19 14:55:55.417 374 1003 I 02300/Locator: OnReceived3 cmd = 12, flags= 0, pid= 1878, uid= 20010033
行 27341: 04-19 14:55:55.417 374 1003 E 02300/CommonUtils: CheckLocationPermission
行 27342: 04-19 14:55:55.418 374 1003 I 02300/Locator: LocatorAbilityStub::ProcessMsgRequirLocationPermission code:12 identity:053691816685942437326882646
行 27344: 04-19 14:55:55.418 374 1003 D 02300/LocationNapi: IsExistFile = 1
行 27345: 04-19 14:55:55.418 374 1003 I 02300/Locator: locator_ability GetAddressByCoordinate
行 27352: 04-19 14:55:55.418 374 1003 I 02300/GeoConvert: GeoConvertServiceStub OnRemoteRequest cmd = 12, flags= 0, pid= 374, uid= 0
行 27353: 04-19 14:55:55.419 374 1003 E 02300/GeoConvert: GeoConvertService::GetAddressByCoordinate
行 27354: 04-19 14:55:55.419 1878 1918 D 02300/Locator_standard: Proxy::GetAddressByCoordinate result from server.
行 27355: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl GetAddressByCoordinate 0
行 27356: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl GetAddressByCoordinate resultSize 1
行 27357: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_localeLanguage
行 27358: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_localeCountry
行 27359: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_placeName
行 27360: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_administrativeArea
行 27361: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_subAdministrativeArea
行 27362: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_locality
行 27363: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_subLocality
行 27364: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_roadName
行 27365: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_subRoadName
行 27366: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_premises
行 27367: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_postalCode
行 27368: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_countryCode
行 27369: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_countryName
行 27370: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_phoneNumber
行 27371: 04-19 14:55:55.419 1878 1918 E 02300/Locator_standard: LocatorImpl Unmarshalling m_addressUrl
行 27372: 04-19 14:55:55.419 1878 1918 I 02300/Locator_standard: Push executeFunc replyList is 0
行 27407: 04-19 14:55:55.422 1878 1878 I 03900/NAPI: [native_api.cpp(napi_get_undefined)] 02300 napi_get_undefined
行 27408: 04-19 14:55:55.422 1878 1878 E 02300/Locator_standard: context->completeFunc
参考日志信息。
g_locatorPtr->GetAddressByCoordinate 只向函数LocatorProxy::GetAddressByCoordinate
int LocatorProxy::GetAddressByCoordinate(MessageParcel &data, MessageParcel &reply)
{
int error;
MessageOption option;
LBSLOGD(LOCATOR_STANDARD, "Proxy::GetAddressByCoordinate1");
sptr<IRemoteObject> remote = Remote();
if (remote == nullptr) {
LBSLOGE(LOCATOR_STANDARD, "GetAddressByCoordinate remote is null");
return EXCEPTION;
}
error = remote->SendRequest(GET_FROM_COORDINATE, data, reply, option);
LBSLOGD(LOCATOR_STANDARD, "Proxy::GetAddressByCoordinate result from server.");
return error;
}
通过 error = remote->SendRequest(GET_FROM_COORDINATE, data, reply, option); 将消息发送出去。LocatorAbilityStub::OnRemoteRequest将处理接受到来的消息。
int32_t LocatorAbilityStub::OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
pid_t callingPid = IPCSkeleton::GetCallingPid();
pid_t callingUid = IPCSkeleton::GetCallingUid();
LBSLOGI(LOCATOR, "OnReceived3 cmd = %{public}u, flags= %{public}d, pid= %{public}d, uid= %{public}d",
code, option.GetFlags(), callingPid, callingUid);
int ret = REPLY_NO_EXCEPTION;
if (data.ReadInterfaceToken() != GetDescriptor()) {
LBSLOGE(LOCATOR, "invalid token.");
return -1;
}
ret = ProcessMsg(code, data, reply, option);
if (ret == MSG_UNPROCESSED) {
ret = ProcessMsgRequirSecureSettingsPermission(code, data, reply, option);
}
if (ret == MSG_UNPROCESSED) {
ret = ProcessMsgRequirLocationPermission(code, data, reply, option);
}
return ret;
}
在函数OnRemoteRequest 中
ret = ProcessMsgRequirLocationPermission(code, data, reply, option);将会通过GET_FROM_COORDINATE 标识,通过GetAddressByCoordinate 获取地址,其中GetAddressByCoordinate 指向函数int LocatorAbility::GetAddressByCoordinate(MessageParcel &data, MessageParcel &replay)
int LocatorAbility::SendGeoRequest(int type, MessageParcel &data, MessageParcel &replay)
{
sptr<IRemoteObject> remoteObject = CommonUtils::GetRemoteObject(LOCATION_GEO_CONVERT_SA_ID,
CommonUtils::InitDeviceId());
if (remoteObject == nullptr) {
return EXCEPTION;
}
MessageOption option;
return remoteObject->SendRequest(type, data, replay, option);
}
remoteObject->SendRequest(type, data, replay, option); 将通过GeoConvertServiceStub 中的OnRemoteRequest再次发送。
int GeoConvertServiceStub::OnRemoteRequest(uint32_t code,
MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
pid_t callingPid = IPCSkeleton::GetCallingPid();
pid_t callingUid = IPCSkeleton::GetCallingUid();
LBSLOGI(GEO_CONVERT, "GeoConvertServiceStub OnRemoteRequest cmd = %{public}u, flags= %{public}d, pid= %{public}d, uid= %{public}d",
code, option.GetFlags(), callingPid, callingUid);
if (callingUid > SYSTEM_UID) {
LBSLOGE(GEO_CONVERT, "this remote request is not allowed");
return -1;
}
if (data.ReadInterfaceToken() != GetDescriptor()) {
LBSLOGE(PASSIVE, "invalid token.");
return EXCEPTION;
}
int ret;
switch (code) {
case IS_AVAILABLE: {
ret = IsGeoConvertAvailable(data, reply);
break;
}
case GET_FROM_COORDINATE: {
ret = GetAddressByCoordinate(data, reply);
break;
}
case GET_FROM_LOCATION_NAME_BY_BOUNDARY: {
ret = GetAddressByLocationName(data, reply);
break;
}
default:
ret = IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
return ret;
}
ret = GetAddressByCoordinate(data, reply);函数将在 GeoConvertService::GetAddressByCoordinate函数获得结果。当前函数应该结果不符合预期,猜测当前函数正在开发中。
int GeoConvertService::GetAddressByCoordinate(MessageParcel &data, MessageParcel &reply)
{
reply.WriteInt32(0);
reply.WriteInt32(1);
return EXCEPTION;
}
至此lamba中函数执行函数流程到此结束。接下来便是asyncContext->completeFunc
asyncContext->completeFunc = [&](void* data) -> void {
ReverseGeoCodeAsyncContext* context = static_cast<ReverseGeoCodeAsyncContext*>(data);
napi_create_array_with_length(context->env, context->replyList.size(), &context->result[PARAM1]);
GeoAddressesToJsObj(context->env, context->replyList, context->result[PARAM1]);
LBSLOGI(LOCATOR_STANDARD, "Push GetAddressesFromLocation result to client");
};
GeoAddressesToJsObj 函数将获取的结果保存到context->result[PARAM1] 中,当然当前版实际结果并没有具体实现,参考LocatorImpl::GetAddressByCoordinate中的replyList.push_back(GeoAddress::Unmarshalling(reply)); 数据存储。
DoCallBackAsyncWork 中数据实际获取结果处理
if (context->errCode != SUCCESS) {
napi_value message = nullptr;
std::string msg = "errCode is " + std::to_string(context->errCode);
napi_create_string_utf8(env, msg.c_str(), NAPI_AUTO_LENGTH, &message);
napi_create_error(env, nullptr, message, &context->result[PARAM0]);
napi_get_undefined(env, &context->result[PARAM1]);
} else {
napi_get_undefined(env, &context->result[PARAM0]);
}
上述代码可以看出,即执行成功之后,JS页面获取结果为undefine即napi_get_undefined(env, &context->result[PARAM0]);
界面获取执行结果:
少见的定位功能讲解!感谢分享。
这方面这的很少,感谢老师分享
你好,请问是用什么设备测试的呢