4、分布式硬件接口开发:分布式硬件接口API、设备能力集查询、硬件资源调用示例
好,咱们进入正题。分布式硬件接口开发,说白了就是让鸿蒙系统里的各个设备能互相“打招呼”,然后调用对方的硬件资源。比如手机调用平板的摄像头,手表调用手机的扬声器——这些都不是魔法,背后就是一套API在干活。
我个人习惯把分布式硬件接口分成三层来看:发现层、能力层、调用层。发现层负责找到设备,能力层负责问清楚“你能干啥”,调用层才是真正用起来。今天咱们重点讲后两层。
4.1 分布式硬件接口API概览
鸿蒙提供的分布式硬件API,核心就几个头文件。我刚开始接触时也被一堆接口搞晕过,后来发现常用的其实不超过10个。
| API名称 | 功能说明 | 使用场景 |
|---|---|---|
GetDeviceCapability() |
查询远端设备的能力集 | 调用前必查,避免“拿不到” |
OpenRemoteHardware() |
打开远端硬件资源 | 摄像头、麦克风等 |
CloseRemoteHardware() |
关闭远端硬件资源 | 用完必须释放 |
RegisterHardwareCallback() |
注册硬件状态回调 | 监听设备插拔、状态变化 |
嗯,这里要注意:所有分布式硬件调用都是异步的。你想想看,网络有延迟,设备可能突然掉线,如果搞成同步阻塞,那用户体验就崩了。所以API设计上,回调函数是标配。
核心原则:先查能力,再调资源。跳过查询直接调用,是我见过最多的翻车现场。
4.2 设备能力集查询
设备能力集,说白了就是一份“设备简历”。上面写着:我有摄像头,分辨率最高1080p;我有扬声器,支持AAC编码;我有陀螺仪,采样率200Hz。
为什么要查这个?我在项目中遇到过这么个事:手机想调用平板的摄像头拍文档,结果平板摄像头只有200万像素,拍出来根本看不清。如果提前查了能力集,就能提示用户“当前设备摄像头分辨率不足”。
查询接口长这样:
// 查询远端设备能力集
int32_t ret = GetDeviceCapability(deviceId, &capability);
if (ret != 0) {
// 查询失败,可能是设备离线了
printf("查询能力集失败,错误码:%d\n", ret);
return;
}
// 解析能力集
if (capability.hasCamera) {
printf("摄像头分辨率:%dx%d\n",
capability.cameraWidth,
capability.cameraHeight);
}
if (capability.hasSpeaker) {
printf("扬声器编码格式:%s\n",
capability.speakerCodec);
}
能力集的数据结构,我一般会重点关注这几个字段:
- hasCamera / hasMic / hasSpeaker —— 有没有这个硬件
- cameraWidth / cameraHeight —— 摄像头分辨率上限
- speakerCodec —— 扬声器支持的音频编码
- sensorType —— 传感器类型列表(加速度、陀螺仪等)
小技巧:能力集查询结果建议缓存起来。每次调用都查一遍,网络开销不小。我一般会在设备连接成功后查一次,然后监听设备状态变化事件,只有变化时才重新查询。
4.3 硬件资源调用示例
好,到了最激动人心的部分——真正调用远端硬件。咱们拿“手机调用平板的摄像头拍照”这个场景来演示。
第一步,打开远端摄像头:
// 打开远端摄像头
RemoteHardwareParam param;
param.deviceId = targetDeviceId;
param.hardwareType = HARDWARE_CAMERA;
param.callback = OnCameraFrameCallback;
int32_t handle = OpenRemoteHardware(¶m);
if (handle < 0) {
printf("打开远端摄像头失败\n");
return;
}
第二步,注册帧回调,接收摄像头数据:
// 帧回调函数
void OnCameraFrameCallback(const FrameData* frame, void* context) {
if (frame == NULL) {
printf("帧数据为空,可能设备断连\n");
return;
}
// 处理图像数据
// 比如保存到本地,或者实时显示
ProcessImage(frame->data, frame->size, frame->width, frame->height);
}
第三步,用完记得关闭:
// 关闭远端摄像头
int32_t ret = CloseRemoteHardware(handle);
if (ret != 0) {
printf("关闭失败,但别慌,系统会自动回收\n");
}
警告:我曾经因为忘记关闭远端摄像头,导致平板摄像头一直被占用,其他应用打不开。分布式资源不像本地资源,系统回收有延迟。所以一定要在合适的时机(比如页面销毁、用户退出)主动关闭。
4.4 避坑指南
做分布式硬件开发,坑不少。我踩过的几个典型:
- 设备突然离线:调用过程中设备断连,回调会收到空指针。一定要做空值检查,否则直接崩溃。
- 权限问题:远端设备也需要申请对应权限。比如调用远端摄像头,远端设备上必须已经授予了相机权限。
- 性能开销:视频流传输很吃带宽。1080p 30fps的视频流,WiFi环境下勉强能跑,4G网络就卡成PPT了。建议根据网络质量动态调整分辨率。
嗯,最后说一句:分布式硬件开发,本质上就是远程过程调用 + 资源管理。把本地硬件调用的经验迁移过来,再注意一下网络异常处理,基本就能上手了。下一章咱们会讲更高级的——如何实现硬件资源的动态迁移,比如手机没电了,自动把摄像头调用切换到平板上。