跳转至

OpenHarmony Native组件开发 用户指南

本文档介绍 HiDiTing SDK 中 OpenHarmony Native 组件的开发方法。内容覆盖 Location、Sensor、Camera 和 HTTP 四类组件:说明组件职责、关键数据结构、场景开发流程、现有 SDK 代码走读以及如何将这些能力集成到自己的 Native 应用中。

各组件的公开接口以 SDK 头文件为准;本文档在具体场景中给出对应头文件和可运行参考代码的位置,避免重复维护接口参数和返回值说明。


OpenHarmony Native组件背景知识

组件职责

OpenHarmony Native 组件向应用提供 C 或 C++ 形式的系统服务能力。应用只调用公开接口和实现回调,不直接访问 GNSS、传感器或相机硬件;底层框架将请求转发到服务和 HDI/HAL,并将异步数据通过回调返回给应用。

原生组件职责关系图

下表给出本指南涉及组件的接口入口、参考实现和典型用途。接口名称可直接跳转到 SDK 中对应的公开声明;参考实现用于理解调用顺序,不建议应用直接依赖内部实现。

组件 Native 接口与用途 SDK 参考实现
Location Locator 提供位置服务使能、定位请求、卫星状态与 NMEA 订阅。 location_sample.cpp
Sensor GetAllSensors()、订阅、启停、批处理和上报模式控制。 sensor_sample.c
Camera CameraKitCameraCameraConfigFrameConfig 提供预览、循环采集和单帧拍照能力。 camera_test.cpp
HTTP HttpClient 提供同步 GET/POST/PUT/DELETE,以及可分步执行的连接、发送和接收流程。 ohosfwk_at_netstack_dfx.cpp

组件选择

业务需求 推荐组件 关键输出
获取经纬度、卫星状态或 NMEA 报文 Location LocationSatelliteStatus、NMEA 字符串回调。
获取加速度、陀螺仪、气压、心率或佩戴状态 Sensor SensorEvent 及其 data 缓冲区。
实现预览、连续帧处理或拍照 Camera Surface 中的帧数据、相机与帧状态回调。
访问 REST 服务、上传数据或下载响应内容 HTTP 状态码、响应头和响应体缓冲区。

组件与编译配置

当前 3322 配置中已经纳入 location_samplesensor_samplecamera_samplenetstack_http 等组件。相关组件列表可在 /src/build/config/target_config/common_config.py/src/build/config/target_config/3322/config.py 中查看。

说明:本文示例命令以一站式 CLI 为主。实际开发可从以下三种环境中选择,推荐使用一站式 CLI。

开发环境 适用场景 使用指南
一站式 CLI(推荐) 快速完成目标选择、构建、烧录和串口监视 一站式 CLI 开发环境使用指南
HiSpark Studio for VS Code 图形化编辑、编译、烧录和调试 HiSpark Studio for VS Code 开发环境使用指南
WSL 与 Docker 在 Windows 上使用一致的 Linux 容器构建环境 WSL 与 Docker 环境使用指南

准备工作:按 一站式 CLI 开发环境使用指南 准备环境、构建和烧录。涉及 GNSS、传感器或相机时,还应确认开发板已具备相应硬件或使用 SDK 提供的模拟实现。


快速跑通定位 Demo

定位组件背景知识

Location 组件目前以 GNSS 定位为核心能力。应用通过 Locator 单例使能位置服务、注册回调并发起定位请求;框架负责管理请求和定位状态,GNSS HDI 负责对接真实芯片或模拟数据源。

图 1 定位子系统架构图

定位子系统架构图

定位子系统包含以下层次:

层次 职责
Interface 提供 Locator、定位结果和 GNSS/NMEA 回调等 C++ 接口。
Framework 实现公开接口,将应用请求转发到 Locator 服务。
Service 管理定位请求、结果上报、定位能力和状态。
GNSS HDI 屏蔽硬件差异,对接 GNSS 芯片或模拟定位数据。

功能与关键数据

类或数据结构 作用
Locator 获取定位服务实例、使能服务、启动/停止定位和订阅 GNSS/NMEA。
ILocatorCallback 接收位置结果、定位状态和错误码。
IGnssStatusCallback 接收卫星数量、方位角、仰角和载噪比等状态。
INmeaMessageCallback 接收 GNSS NMEA 标准报文。
Location 保存经纬度、高度、速度和方向等定位结果。
RequestConfig 配置定位场景、优先级和时间间隔。

RequestConfig 的优先级应按业务选择:PRIORITY_ACCURACY 优先定位精度,PRIORITY_LOW_POWER 适合低功耗周期定位,PRIORITY_FAST_FIRST_FIX 用于优先获得首次定位结果。完整枚举定义见 /src/ohos/base/location/location_lite/interfaces/kits/include/constant_definition.h

定位开发流程

定位组件开发流程

核心接口

操作 接口 说明
获取实例、查询/使能服务 Locator::GetInstanceIsLocationEnabledEnableAbility 先确认服务状态,再执行使能或去使能。
启动/停止定位 StartLocatingStopLocating 启动时同时传入请求配置和位置回调;停止时传入同一回调对象。
卫星/NMEA 订阅 RegisterGnssStatusCallbackRegisterNmeaMessageCallback 应在启动定位前注册,退出时成对注销。
查询坐标系 QuerySupportCoordinateSystemType 根据返回列表选择应用使用的坐标系。

关键配置

HiDiTingV100 默认提供 GNSS Emulator,在未接入实际 GNSS 芯片时读取 /user/gnss_nmea.log 中的 NMEA 数据并按固定周期上报。数据文件路径由 /src/ohos/drivers/peripheral/location/gnss/gnss_emulator/source/gnss_emulator_vendor_impl.cppg_gnssNmeaFile 配置。

接入实际 GNSS 芯片时,应完成芯片驱动和 GNSS HDI 适配;GNSS 组件选择和构建入口位于 /src/ohos/drivers/peripheral/location/CMakeLists.txt。使用辅助定位数据时,需要先确保板端时间有效,再将解析后的数据放入业务所需目录。

核心代码与走读

以下代码展示最小定位请求的关键调用顺序:

using namespace OHOS::Location;

Locator &locator = Locator::GetInstance();
bool enabled = false;
if (locator.IsLocationEnabled(enabled) == ERRCODE_SUCCESS && !enabled) {
    (void)locator.EnableAbility(true);
}

RequestConfig requestConfig;
requestConfig.SetPriority(PRIORITY_ACCURACY);

(void)locator.RegisterGnssStatusCallback(&gnssStatusCallback);
(void)locator.RegisterNmeaMessageCallback(&nmeaMessageCallback);
(void)locator.StartLocating(&requestConfig, &locationCallback);

结束定位时,按下面顺序释放:

(void)locator.StopLocating(&locationCallback);
(void)locator.UnregisterNmeaMessageCallback(&nmeaMessageCallback);
(void)locator.UnregisterGnssStatusCallback(&gnssStatusCallback);

SDK 参考代码与走读/src/ohos/base/location/location_lite/sample/location_sample.cpp 中:

  1. LocationEnableLocating() 获取 Locator 单例,查询服务状态后调用 EnableAbility(true)
  2. LocationStartLocating() 先注册卫星和 NMEA 回调,再以 PRIORITY_ACCURACY 构造 RequestConfig 并调用 StartLocating()
  3. LocatorCallback::OnLocationReport() 读取纬度、经度、高度、速度和方向;OnErrorReport()OnLocatingStatusChange() 用于维护业务状态。
  4. LocationStopLocating() 先注销附加回调,再停止位置请求,避免停止后继续处理无效数据。

预期结果与调试

定位服务使能后,OnLocationReport() 持续输出位置数据;注册卫星状态和 NMEA 回调后,可分别看到卫星信息和 NMEA 报文。使用模拟定位时,首先检查 /user/gnss_nmea.log 是否存在且内容符合 NMEA 格式;使用真实芯片时,优先检查 HDI 初始化、串口/I2C 连接和芯片定位状态。


快速跑通传感器 Demo

传感器组件背景知识

Sensor 组件为轻量设备提供统一的传感器查询、订阅、批处理、上报模式和启停能力。应用通过 SensorUser 注册回调,服务层在收到硬件或虚拟传感器数据时以 SensorEvent 形式上报。

图 2 传感器子系统架构图

传感器子系统架构图

层次 职责
Interface 提供传感器列表查询、订阅、启停、模式和批处理配置接口。
Framework 向上分发传感器数据,向下调用传感器服务。
Service 管理订阅用户、数据上报和传感器状态。
Sensor HDI 对接物理传感器或虚拟传感器实现,屏蔽硬件差异。

关键数据与功能表

数据结构或类型 作用
SensorInfo 描述传感器名称、厂商、类型、量程、精度和功耗。
SensorEvent 上报传感器类型、时间戳、模式、数据指针和数据长度。
SensorUser 保存订阅者名称、数据回调和用户数据。
SensorTypeId 标识物理或虚拟传感器类型。
SensorMode 默认、实时、按变化、单次和 FIFO 上报模式。

SDK 示例覆盖的传感器如下表所示。实际可用列表以 GetAllSensors() 返回的结果为准。

示例名称 类型标识 典型数据
加速度计 SENSOR_TYPE_ID_ACCELEROMETER AccelData 的 X/Y/Z 轴数据。
气压计 SENSOR_TYPE_ID_BAROMETER PressureData 的气压、温度和有效标识。
陀螺仪 SENSOR_TYPE_ID_GYROSCOPE GyroData 的 X/Y/Z 轴数据。
心率 SENSOR_TYPE_ID_HEART_RATE 单个心率值。
佩戴检测 SENSOR_TYPE_ID_WEAR_DETECTION 佩戴状态。
计步器 SENSOR_TYPE_ID_PEDOMETER 步数或计步状态。
虚拟加速度算法 SENSOR_TYPE_ID_VSENSOR_ACCELEROMETER_ALG_SIMU 算法处理后的虚拟传感器数据。

传感器开发流程

传感器组件开发流程

核心接口

操作 接口 说明
查询支持的传感器 GetAllSensors 返回 SensorInfo 数组和数量,先确认设备能力。
订阅/取消订阅 SubscribeSensorUnsubscribeSensor 同一个 SensorUser 对象应贯穿订阅和取消订阅。
使能/去使能 ActivateSensorDeactivateSensor 使能后才会向订阅用户上报数据。
设置批处理 SetBatch 设置采样间隔和上报间隔。
设置模式 SetMode 使用 SensorMode 选择上报策略。

核心代码与走读

回调中必须先校验 datadataLensensorTypeId,再将数据转换为该类型对应的结构:

static void RecordAccelSensorCallback(SensorEvent *event)
{
    if (event == NULL || event->data == NULL ||
        event->sensorTypeId != SENSOR_TYPE_ID_ACCELEROMETER ||
        event->dataLen % sizeof(AccelData) != 0) {
        return;
    }

    uint32_t count = event->dataLen / sizeof(AccelData);
    AccelData *data = (AccelData *)event->data;
    for (uint32_t i = 0; i < count; i++) {
        /* 使用 data[i].axisX、axisY、axisZ。 */
    }
}

static SensorUser g_accelUser = {
    .name = "native_accel",
    .callback = RecordAccelSensorCallback,
};

(void)SubscribeSensor(SENSOR_TYPE_ID_ACCELEROMETER, &g_accelUser);
(void)ActivateSensor(SENSOR_TYPE_ID_ACCELEROMETER, &g_accelUser);

SDK 参考代码与走读/src/ohos/base/sensors/sensor_lite/sample/sensor_sample.c 中:

  1. SensorGetAllSensors() 通过 GetAllSensors() 缓存设备支持的列表。
  2. SensorSubscribe() 在调用 SubscribeSensor() 前检查本地订阅状态,避免重复订阅。
  3. SensorActivate() 仅在未使能时调用 ActivateSensor()SensorSetBatch()SensorSetMode() 在同一 SensorUser 上配置采样与上报行为。
  4. RecordAccelSensorCallback()RecordBarSensorCallback()RecordCyroSensorCallback() 均先检查长度和传感器类型,再按对应数据结构解析。
  5. SensorDeactivate() 在去使能前处理已订阅状态,应用退出时应确保订阅和使能状态均已清理。

传感器驱动适配与预期结果

当前 SDK 可使用模拟传感器实现;对接新硬件传感器时,应在 /src/ohos/drivers/peripheral/sensor/hal_lite/sensors 下实现对应 HDI 插件,并在 /src/ohos/drivers/peripheral/sensor/CMakeLists.txt 中纳入构建。

使能并订阅有效传感器后,数据回调应持续收到与类型匹配的 SensorEvent。若无数据,依次检查 GetAllSensors() 是否包含该类型、是否已订阅并使能、采样间隔是否合理,以及传感器 HDI 是否已初始化。


快速跑通相机 Demo

相机组件背景知识

Camera 组件通过 CameraLite 框架提供相机枚举、能力查询、相机创建、预览、循环采集和单帧拍照能力。应用创建 Camera 后,在 CameraStateCallback::OnCreated() 回调内完成相机配置;每种业务将 Surface 加入 FrameConfig,再触发预览、录像或拍照。

图 3 Camera子系统架构图

Camera子系统架构图

层次 职责
Camera 应用 创建相机、配置 Surface、处理帧与状态回调。
CameraLite 提供 Native 相机接口及业务状态管理。
Camera HAL 屏蔽具体摄像头的初始化、能力和 Buffer 填充差异。
驱动层 提供 GPIO、I2C、ISP 和视频输入等硬件能力。

Camera NAPI 与关键数据表

核心接口 用途
CameraKit GetInstanceGetCameraIdsGetCameraAbilityCreateCamera 获取相机框架、枚举相机、查询能力并异步创建相机。
Camera ConfigureTriggerLoopingCaptureStopLoopingCaptureTriggerSingleCaptureRelease 配置设备、启动/停止循环采集、单帧拍照和释放资源。
CameraConfig CreateCameraConfig、帧状态回调配置 为相机设置帧回调和事件处理器。
FrameConfig 预览/录像/拍照类型、AddSurface、参数设置 承载单个采集业务的 Surface 和帧参数。
FrameConfig 类型 用途 典型 Surface 行为
FRAME_CONFIG_PREVIEW 预览 将 Surface 配置到 UI 控件树中显示画面。
FRAME_CONFIG_RECORD / FRAME_CONFIG_CALLBACK 循环采集或码流处理 通过帧回调获取 Buffer,进行录制、编码或发送。
FRAME_CONFIG_CAPTURE 单帧拍照 单次采集完成后从 Surface 获取图像数据。

相机开发流程

相机组件开发流程

关键配置与硬件适配

Camera 业务由 diting-community-native-js 目标中的 camera_samplecamera_litecamera_hal 等组件提供支持,相关配置见 /src/build/config/target_config/3322/config.py

图 4 watch_type 配置示意

watch_type配置为kid

当前 3322 目标的 watch_type 取值位于 /src/build/config/target_config/3322/target_config.py。相机功能应优先确认目标已启用 diting-community-native-js 对应的 Camera 组件,而不是仅依据截图修改配置项。

适配特定摄像头时,重点检查 /src/middleware/services/media/hal/camera_lite 的 GPIO 复位、IO 引脚、I2C 地址、寄存器初始化序列以及 HalCameraGetStreamCap() 上报的分辨率和帧率能力。

核心代码与走读

相机创建和配置应在回调链中完成:

CameraKit *cameraKit = CameraKit::GetInstance();
std::list<std::string> cameraIds = cameraKit->GetCameraIds();
if (!cameraIds.empty()) {
    cameraKit->CreateCamera(cameraIds.front(), cameraStateCallback, eventHandler);
}

void DemoCameraStateCallback::OnCreated(Camera &camera)
{
    CameraConfig *config = CameraConfig::CreateCameraConfig();
    config->SetFrameStateCallback(&frameStateCallback, &eventHandler);
    camera.Configure(*config);
    camera.TriggerLoopingCapture(previewFrameConfig);
}

SDK 参考代码与走读/src/ohos/foundation/multimedia/camera_lite/sample/camera_test.cpp 中:

  1. CameraInit() 取得 CameraKit,读取相机 ID 列表并调用 CreateCamera();相机对象只有在 OnCreated() 后可用。
  2. OnCreated() 创建 CameraConfig、注册帧状态回调、调用 Configure(),然后保存 Camera 指针。
  3. SetFrameConfig()CreateSurface() 为预览、录像和拍照创建匹配的 Surface 与帧参数;Surface 为空时不可启动采集。
  4. StartPreview()/StopPreview() 调用循环采集接口;Capture() 调用 TriggerSingleCapture() 后从 Surface 获取图像数据;业务结束时调用 Release() 并清理 Surface。

预期结果与调试

预览场景中,Camera 创建与配置成功后 UI Surface 显示画面;拍照场景中,单帧完成后可以从 Surface 获取 Buffer。若 GetCameraIds() 返回空列表,先检查相机 HAL 是否加载、硬件连接与 I2C 通信是否正常;若创建成功但无画面,检查 FrameConfig 类型、Surface 尺寸/格式和 HalCameraGetStreamCap() 返回的能力是否匹配。


快速跑通 HTTP Demo

HTTP组件背景知识

HTTP 组件提供两类使用方式:HttpClientGetRequest 等同步接口适用于一次性 GET、POST、PUT、DELETE 请求;HttpClientConnHttpClientSendHttpClientRecvResponse 适用于需要控制连接、发送和分块接收的场景。所有接口在调用线程中执行,网络业务不应阻塞 UI 或高优先级任务。

HTTP 请求、数据与错误码表

场景 接口 说明
同步请求 HttpClientGetRequestHttpClientHeadRequestHttpClientPostRequestHttpClientPutRequestHttpClientDelete 以 URL 为输入,调用完成后获得响应。
分步请求 HttpClientConnHttpClientSendHttpClientRecvResponseHttpClientClose 分别建立连接、发送请求、循环接收响应和关闭连接。
请求扩展 HttpClientSetCustomHeaderHttpClientGetResponseCode 设置自定义请求头,获取 HTTP 状态码。
HttpClientData 字段 作用
postBuf / postBufLen / postContentType POST/PUT 请求体、长度和内容类型。
responseBuf / responseBufLen 响应体缓冲区及长度;缓冲区由应用准备。
headerBuf / headerBufLen 响应头缓冲区及长度。
contentBlockLen / responseContentLen 本次接收的数据长度和响应体总长度。
isMore / isChunked 指示是否还需要继续接收,以及响应是否采用分块传输。
isRedirected / redirectUrl 指示是否收到重定向及重定向地址。
结果码 含义
HTTP_SUCCESS 成功。
HTTP_EAGAIN 仍有数据需要继续获取。
HTTP_ENOBUFS / HTTP_EARG / HTTP_ENOTSUPP 缓冲区不足、参数错误或功能不支持。
HTTP_EDNS / HTTP_ECONN DNS 解析或连接失败。
HTTP_ESEND / HTTP_ERECV / HTTP_ECLSD 发送失败、接收失败或连接已关闭。
HTTP_EPARSE / HTTP_EPROTO / HTTP_EUNKNOW / HTTP_ETIMEOUT URL 解析、协议、未知或超时错误。

完整的 HttpClientHttpClientDataHTTPC_RESULT 定义见 /src/ohos/foundation/arkui/ace_engine_lite/frameworks/src/core/modules/netstack/http/include/httpclient.h

HTTP开发流程

HTTP组件开发流程

核心代码与走读

以下示例使用分步接口处理可能分块返回的响应:

HttpClient client = {0};
HttpClientData data = {0};
HTTPC_RESULT ret = HTTP_SUCCESS;
char response[2048] = {0};
char header[2048] = {0};

data.responseBuf = response;
data.responseBufLen = sizeof(response);
data.headerBuf = header;
data.headerBufLen = sizeof(header);
client.timeoutMs = 40000;

    ret = HttpClientConn(&client, url);
    if (ret != HTTP_SUCCESS) {
        goto exit;
    }

    ret = HttpClientSend(&client, url, HTTP_GET, &data);
    if (ret != HTTP_SUCCESS) {
        goto exit;
    }

    do {
        ret = HttpClientRecvResponse(&client, &data);
        /* 本轮数据长度为 data.contentBlockLen,应在下一轮接收前处理或复制。 */
        if (ret < HTTP_SUCCESS && ret != HTTP_EAGAIN) {
            break;
        }
    } while (ret == HTTP_EAGAIN || data.isMore);

exit:
    HttpClientClose(&client);
    return ret;
}

HttpClientRecvResponse() 要求 headerBufLenresponseBufLen 均不小于 2048 字节;代码中的两个 2048 字节数组满足该要求。每次接收后,响应体有效长度由 contentBlockLen 给出,不能将整个缓冲区都视为本轮有效数据。

SDK 参考代码与走读/src/middleware/utils/at/at_ohos_cmd/at/at_ohos_process_cpp/ohosfwk_at_netstack_dfx.cpp 按“配置缓冲区 → HttpClientConn()HttpClientSend() → 循环 HttpClientRecvResponse()HttpClientClose()”处理网络诊断请求;/src/application/wearable/service/amap_adapter/amap_os_adapter/amap_net_adapter.c 对连接、发送和接收分别检查错误并在结束路径统一关闭连接。

预期结果与调试

网络连通且 URL 正确时,HttpClientGetResponseCode() 返回服务端状态码,响应头写入 headerBuf,响应体分段写入 responseBuf。若使用 4G CAT1 公网访问,先确认 DNS、网络注册和 IP 获取状态;遇到 HTTP_EAGAIN 时继续接收,遇到负错误码时按错误类别定位 DNS、连接、发送、接收或超时问题。


基于 Native 组件 Demo 开发自己的组件

下面以“定位、传感器和 HTTP 上报”类应用为例说明如何建立自己的 Native 组件应用;相机应用可沿用同样的组件组织和资源释放模式。

  1. 建立独立组件。/samples/native_samples/ 下创建目录,并参考 /samples/native_samples/adc/CMakeLists.txt 编写 CMakeLists.txt。在 /samples/native_samples/CMakeLists.txt 中通过功能宏和 add_subdirectory_if_exist() 纳入组件。
  2. 声明需要的头文件路径。 Location、Sensor、Camera 和 HTTP 分别加入对应公开头文件所在目录。C++ 组件需在 CMakeLists.txt 中启用 C++ 编译并使用与 SDK 示例一致的 C++ 标准和编译选项;可参考 /src/ohos/base/location/location_lite/sample/CMakeLists.txt/src/ohos/foundation/multimedia/camera_lite/sample/CMakeLists.txt
  3. 先实现异步回调和业务状态。 Location 的三类回调、Sensor 的 RecordSensorCallback、Camera 的状态/帧回调都应在应用对象生命周期内保持有效。使用状态机记录“未初始化、已订阅、已使能、运行中、释放中”,不要只依赖接口的同步返回值。
  4. 按资源获取的反向顺序释放。 停止定位后注销定位附加回调;传感器先去使能再去订阅;相机停止采集后释放相机和 Surface;HTTP 在所有成功和失败分支中调用 HttpClientClose()
  5. 逐模块验证。 先验证 Location/Sensor/Camera/HTTP 的单一功能和回调日志,再将数据处理、UI 显示或网络上报组合到同一应用,避免把硬件适配和业务逻辑问题混在一起排查。

建议每个组件使用独立源文件,例如 native_location.cnative_sensor.cnative_camera.cppnative_http.c,由应用入口统一初始化和停止。这样可以保持 C/C++ 编译边界清晰,也便于按需裁剪组件。

可编译应用的组件注册链路

在 GitCode 的 native_samples 示例目录中创建应用子目录后,还需要完成“目录注册 → 功能宏 → 目标组件”三步,应用才会参与目标构建。以下链路与现有 Native 组件的注册方式一致。

原生组件注册流程

  1. 在上述 native_samples 目录中为应用建立独立子目录,创建源码和 CMakeLists.txt,并为组件指定唯一的 COMPONENT_NAME,例如 native_ohos_app
  2. /samples/native_samples/CMakeLists.txt 中加入功能宏控制,避免默认构建时无条件纳入所有应用:

    if("CONFIG_ENABLE_NATIVE_OHOS_APP" IN_LIST DEFINES)
        add_subdirectory_if_exist(native_ohos_app)
    endif()
    
  3. 在选用目标的 /src/build/config/target_config/3322/config.py 中增加 CONFIG_ENABLE_NATIVE_OHOS_APP,并在对应的 ram_component 中加入 native_ohos_app。Location、Sensor、Camera 或 HTTP 应用还必须选择已纳入 OpenHarmony 框架组件的目标;当前 diting-community-native-js 已启用 SUPPORT_OHOSFWK,并纳入 Camera 相关组件。

  4. 一站式 CLI 开发环境使用指南 构建和烧录。若只需要一个组件,应先验证该组件在当前目标中已启用,再加入自己的应用组件。

C 组件 CMake 模板

Sensor 和 HTTP 可使用 C 源文件。以下模板以“传感器采集并通过 HTTP 上报”为例;仅保留应用所需头文件目录,组件依赖仍由目标配置中的 OpenHarmony 组件提供。

set(COMPONENT_NAME "native_ohos_app")

set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/native_ohos_app.c
    ${CMAKE_CURRENT_SOURCE_DIR}/native_sensor.c
    ${CMAKE_CURRENT_SOURCE_DIR}/native_http.c
)

set(PUBLIC_HEADER
    ${CMAKE_CURRENT_SOURCE_DIR}
)

set(PRIVATE_HEADER
    ${ROOT_DIR}/ohos/base/sensors/sensor_lite/interfaces/kits/native/include
    ${ROOT_DIR}/ohos/drivers/peripheral/sensor/interfaces/include
    ${ROOT_DIR}/ohos/foundation/arkui/ace_engine_lite/frameworks/src/core/modules/netstack/http/include
)

set(PRIVATE_DEFINES)
set(PUBLIC_DEFINES)
set(COMPONENT_CCFLAGS)
set(WHOLE_LINK true)
set(MAIN_COMPONENT false)

build_component()

若应用只使用 HTTP,应删除 Sensor 相关源文件和头文件目录;若只使用 Sensor,应删除 HTTP 相关目录。不要将未使用的组件和驱动一并纳入,避免增加镜像体积和初始化依赖。

C++ 组件 CMake 模板

Location 和 Camera 使用 C++ 接口。Location 应用可先使用以下最小模板;Camera 应用除 C++ 编译选项外,还应以 /src/ohos/foundation/multimedia/camera_lite/sample/CMakeLists.txt 为准补齐 UI、Surface、IPC 和 Camera 框架头文件目录。

enable_language(CXX)
set(COMPONENT_NAME "native_ohos_location_app")

set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/native_ohos_location_app.cpp
)

set(PUBLIC_HEADER
    ${CMAKE_CURRENT_SOURCE_DIR}
)

set(PRIVATE_HEADER
    ${ROOT_DIR}/ohos/base/location/location_lite/interfaces/kits/include
    ${ROOT_DIR}/ohos/base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite
)

set(COMPONENT_FLAGS)
list(REMOVE_ITEM COMPONENT_FLAGS -std=gnu99 -std=c99 -std=gnu11 -std=c11)
list(APPEND COMPONENT_FLAGS
    -std=c++11
    -fno-exceptions
    -fno-unwind-tables
    -fno-asynchronous-unwind-tables
    -nostdlibinc
)
set(COMPONENT_CCFLAGS ${COMPONENT_FLAGS})
set(WHOLE_LINK true)
set(MAIN_COMPONENT false)

build_component()

该模板与 /src/ohos/base/location/location_lite/sample/CMakeLists.txt 的语言和头文件配置保持一致。C++ 应用的回调类、LocatorCameraKitCameraFrameConfig 和 Surface 对象不得跨语言边界以 C 结构体方式处理。

四类应用的实现契约

下表说明一个完整应用在初始化、运行和退出阶段必须实现的行为。这些约束补足了仅调用单个接口时容易遗漏的状态和资源管理。

组件 初始化契约 运行契约 停止与资源释放
Location 获取 Locator,确认并使能服务;创建位置、卫星和 NMEA 回调对象。 先注册附加回调,再调用 StartLocating();位置数据在 OnLocationReport() 中处理。 StopLocating() 后注销 NMEA 与卫星回调;最后按需去使能服务。
Sensor 调用 GetAllSensors() 确认可用类型;创建生命周期足够长的 SensorUser 订阅、使能,再按需配置 SetBatch()SetMode();严格按 sensorTypeId/dataLen 解析。 DeactivateSensor(),再 UnsubscribeSensor();清除本地已订阅/已使能状态。
Camera 获取 CameraKit 和相机 ID;准备相机状态、帧状态回调与事件处理器。 仅在 OnCreated() 后配置 CameraConfig、Surface 和 FrameConfig,再启动采集。 停止循环采集,释放 Buffer/Surface,调用 Release();使回调不再访问已释放对象。
HTTP 准备 HttpClientHttpClientData、响应头和响应体缓冲区;确认网络已连接。 执行同步请求,或采用连接、发送、循环接收的分步流程;按 contentBlockLen 消费本轮数据。 所有成功和失败路径均调用 HttpClientClose();应用负责释放自身申请的缓冲区。

最小应用骨架

以下骨架适合将各组件拆分为独立初始化与停止函数。它避免在应用入口中混杂业务处理、回调和资源释放逻辑:

static int native_app_start(void)
{
    int ret = native_sensor_start();
    if (ret != SENSOR_OK) {
        return ret;
    }

    ret = native_http_init();
    if (ret != HTTP_SUCCESS) {
        native_sensor_stop();
        return ret;
    }
    return 0;
}

static void native_app_stop(void)
{
    native_http_deinit();
    native_sensor_stop();
}

Location 和 Camera 应用以 C++ 类封装相同的 Start()/Stop() 语义。应用初始化失败时,应只释放已经成功获取的资源;退出路径可以重复调用而不产生二次释放。

AI 开发自检清单

在生成应用代码前,依次确认下列信息。缺少其中任一项时,不应假设硬件存在或接口可用。

检查项 Location Sensor Camera HTTP
目标与组件 SUPPORT_OHOSFWK、Location 组件 sensor_clientsensor_servicesensor_hdi camera_litecamera_hal、目标 UI 配置 SUPPORT_LWIPnetstack_http
外部条件 GNSS 芯片或 NMEA 模拟文件 有效 Sensor HDI 或模拟传感器 摄像头、GPIO/I2C/ISP 与 HAL 能力 网络注册、DNS、服务端 URL/证书
回调/缓冲区 三类回调对象在定位结束前有效 SensorUser 和事件解析缓冲区有效 相机、Surface、帧回调在释放前有效 头/体缓冲区长度、分块接收状态有效
最小验收信号 位置/卫星/NMEA 回调日志 GetAllSensors() 列表和 SensorEvent 相机 ID、OnCreated()、帧完成或预览画面 HTTP 状态码、响应头、响应体

Native 组件扩展边界

本指南的 Demo 面向 Native 应用开发。若目标是新增系统级组件或适配新硬件,还需以对应 HDI/HAL 的实现和硬件资料为准:

扩展目标 需要补充的实现依据 主要入口
新 GNSS 芯片 芯片通信协议、初始化时序、NMEA/定位数据格式和 GNSS HDI 实现。 /src/ohos/drivers/peripheral/location/gnss
新传感器或虚拟传感器 传感器寄存器说明、量程/精度、采样与上报语义、HDI 插件实现。 /src/ohos/drivers/peripheral/sensor/hal_lite
新摄像头 GPIO、I2C 地址、寄存器初始化、ISP 参数、支持的分辨率和帧率。 /src/middleware/services/media/hal/camera_lite
网络协议扩展 服务端协议、身份认证、证书、超时/重试和数据持久化策略。 /src/ohos/foundation/arkui/ace_engine_lite/frameworks/src/core/modules/netstack/http

因此,AI 可以依据本文档和 SDK 实现完成 Native 应用;在新增硬件组件时,仍必须取得目标器件的硬件资料和通信协议,再完成 HDI/HAL 适配及板级验证。


注意事项

  • Location、Sensor 和 Camera 的结果均为异步回调;回调对象和其依赖缓冲区必须在取消订阅、停止或释放前保持有效。
  • GNSS Emulator 仅用于验证定位流程,不代表真实 GNSS 芯片的首次定位时间、卫星数量和精度。
  • Sensor 回调必须根据 sensorTypeIddataLen 选择正确的数据结构,禁止把一种传感器的 data 直接转换为另一种类型。
  • Camera 的 CreateCamera() 是异步操作,只能在 OnCreated() 之后调用 Configure() 和采集接口;Surface、帧格式、分辨率和相机能力必须匹配。
  • HTTP 接口会阻塞调用线程。响应可能分段返回,应用需依据 HTTP_EAGAINisMore 持续接收,并始终关闭连接。
  • 业务代码只包含公开头文件,不应直接调用组件内部的 Service、HDI 或 HAL 实现函数。

常见编译错误

现象 排查方法
找不到 locator.hsensor_agent.hcamera_kit.hhttpclient.h 检查组件 CMakeLists.txtPRIVATE_HEADER 是否加入本文“组件职责”表中对应公开头文件的所在目录。
C++ Location/Camera 代码按 C 编译 参考 Location/Camera 示例的 CMakeLists.txt 启用 C++ 编译,并使用 C++ 源文件扩展名。
链接阶段找不到 Location、Sensor、Camera 或 HTTP 符号 确认选择的目标已纳入对应组件;参照 /src/build/config/target_config/common_config.py/src/build/config/target_config/3322/config.py 检查配置。
SensorEvent 数据长度或类型不匹配 在回调中同时校验 sensorTypeIddatadataLen 和批次数量;不要假设所有传感器均为单个三轴数据。
Camera 创建失败或没有预览画面 检查相机 ID、HAL、I2C/GPIO、FrameConfig 类型、Surface 配置和能力集。
HTTP 返回 HTTP_EDNSHTTP_ECONNHTTP_ETIMEOUT 检查网络注册、DNS、URL、TLS 证书配置、超时值和响应接收循环。