HarmonyOS 7 NearLink SSAP 实战:Client/Server 建链、服务发现与近场数据通信

两台设备离得再近,不知道对方是谁、能干嘛,也传不了数据。

文章封面

做近场投屏控制的时候,最开始以为就是"设备靠近了直接连",结果实际做下来发现不是那么回事:先得发现附近有什么设备,然后得确认对方能提供什么服务,再建立连接,最后才能开始传数据。

这一套流程下来,才把手机往平板发实时控制指令的功能跑通。这篇就沿着"两台设备第一次见面"这个过程,把 NearLink SSAP 的建链、发现、通信、断开整个生命周期拆清楚。

一、SSAP 是什么角色

先把概念理清楚:

概念作用
NearLink近场通信技术底层
SSAP上层的服务访问协议
Server提供服务的设备
Client连接服务的设备
Service一组相关能力的集合
CharacteristicService 里的具体数据点

可以把整个过程想成打电话:

  • Server 是总机,有若干条业务线(Service);
  • Client 是打电话的人,先得知道总机号码(发现设备);
  • 然后要拨对应的业务线(连接 Service);
  • 最后才能在这条线上传数据(读写 Characteristic)。

二、设备发现和业务通信不是一回事

最容易犯的错就是把"设备发现"和"业务通信"混为一谈。

阶段做什么状态
发现扫描附近有哪些设备还没连上
建链和目标设备建立连接连接中
服务发现查询对方有哪些 Service已连接
数据通信读写 Characteristic 传数据通信中

发现设备只是知道"附近有这么个东西",不代表你已经能和它传数据了。发现完了还要建链、还要查服务、还要确认特征值,这一套走完才能真正传数据。

三、Server 侧怎么启动服务

Server 侧要做的事:启动 NearLink、创建 Server、注册 Service 和 Characteristic、开始监听连接。

这段代码解决什么问题: 在 Server 侧注册近场服务和特征值。
文件: ssap/Server.ets
用途: 启动 SSAP 服务端
接入位置: 服务启动阶段

import nearLink from '@ohos.nearlink';

class ControlServer {
  private ssapServer: nearLink.ssap.SsapServer;

  async start() {
    // 创建 Server
    this.ssapServer = nearLink.ssap.createSsapServer('control_service_id');
    
    // 注册 Service 和 Characteristic
    this.ssapServer.addService({
      serviceId: '12345678-1234-1234-1234-1234567890ab',
      characteristics: [{
        characteristicId: '87654321-4321-4321-4321-ba0987654321',
        properties: ['read', 'write', 'notify']
      }]
    });
    
    // 开始监听
    this.ssapServer.startAdvertising();
  }
}

这里 Service 和 Characteristic 的 ID 要提前定义好,Client 侧也要用同样的 ID 才能找到对应的服务。

四、Client 侧怎么连接和读写

Client 侧的流程是:扫描设备 → 找到目标 → 建立连接 → 发现服务 → 找到特征值 → 读写数据。

这段代码解决什么问题: Client 连接 Server 并发送控制指令。
文件: ssap/Client.ets
用途: 近场客户端连接与数据发送
接入位置: 点击"连接设备"按钮

class ControlClient {
  private ssapClient: nearLink.ssap.SsapClient;

  async connect(deviceAddress: string) {
    this.ssapClient = nearLink.ssap.createSsapClient();
    
    // 建立连接
    await this.ssapClient.connect(deviceAddress);
    
    // 发现服务
    const services = await this.ssapClient.discoverServices();
    
    // 找到目标特征值
    const char = services[0].characteristics[0];
    
    // 写入数据
    await this.ssapClient.writeCharacteristic(char, new TextEncoder().encode('play_pause'));
  }
}

这里要注意:连接成功之后不能马上就写数据,必须等服务发现完成、确认特征值存在之后再写。很多人连接一成功就直接发数据,结果因为服务还没发现完,写入直接失败。

业务流程图

五、连接状态变化要监听

近场连接不是一劳永逸的。设备走远了、信号断了、对方退出了,连接都会断开。

状态触发场景处理方式
已连接建链成功更新 UI,允许操作
已断开距离远/对方退出更新 UI,提示重连
重连中网络恢复自动重连逻辑

必须监听连接状态变化。如果断线了还保留着旧的连接状态,UI 上显示"已连接",但实际数据根本发不出去,用户操作半天没反应。

六、几个容易踩的坑

第一个坑:重复创建 Server。每次页面进入都创建一个新的 Server,结果端口冲突、服务重复注册。Server 应该全局只创建一次。

第二个坑:连接成功就立即发送业务数据。服务还没发现完,特征值还没找到,这时候写数据肯定失败。必须等服务发现完成之后再发。

第三个坑:Service/Characteristic 标识管理混乱。两边 ID 对不上,找不到对应的服务,连接上了但通信失败。这些 ID 要统一定义,不能两边各写各的。

第四个坑:断线后保留旧连接状态。UI 显示已连接,实际连接已经断了,操作没反应。必须监听断开事件,及时更新状态。

第五个坑:高频小数据无限发送。控制指令发得太频繁,带宽占满了反而延迟更高。要做节流,控制发送频率。

第六个坑:页面退出后没有释放资源。监听没取消、连接没断开、Server 没停止,资源一直占着。

运行效果图

这次做近场控制最大的体会是:近场通信不是"设备靠近就连上"那么简单。从发现、建链、查服务、传数据,到断线重连、资源释放,每一步都有自己的时机和边界。把生命周期想清楚了,代码其实不难;没想清楚就直接开写,很容易在"连接上了但传不了数据"这种问题上卡很久。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值