定位模块之getAddressesFromLocation函数解析 原创 精华

挖墙脚的农民工
发布于 2022-4-21 08:55
浏览
4收藏

::: 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进行组合。
执行体:
定位模块之getAddressesFromLocation函数解析-鸿蒙开发者社区
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]);
界面获取执行结果:
定位模块之getAddressesFromLocation函数解析-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-4-21 08:55:24修改
6
收藏 4
回复
举报
3条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

少见的定位功能讲解!感谢分享。

回复
2022-4-21 09:51:02
科技维度
科技维度

这方面这的很少,感谢老师分享

 

回复
2022-4-22 09:34:43
安苒anran0
安苒anran0

你好,请问是用什么设备测试的呢

回复
2024-1-24 15:52:22
回复
    相关推荐