尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

《HarmonyOS技术精讲-NearLink Kit(星闪服务)》第1篇:初识星闪——NearLink Kit概述与Hello World

《HarmonyOS技术精讲-NearLink Kit(星闪服务)》第1篇:初识星闪——NearLink Kit概述与Hello World
📅 发布时间:2026/7/17 1:41:59

初识星闪:NearLink Kit不会凭空工作

很多人第一次打开华为 NearLink 的官方文档,会觉得这个功能挺简单:引入@kit.ConnectKit下的nearlink模块,调用discover方法,就能发现周围设备了。但实际写代码的时候,你会发现几个诡异的问题:

  1. 模拟器上什么也扫不到。
  2. 真机上好不容易扫到了,页面一退,回调就不走了。
  3. 明明手机都贴在一起了,就是发现不了。

HarmonyOS NearLink 服务不是蓝牙的一个变种,也不是 Wi-Fi Direct 的替换。它的底层机制、权限模型和生命周期管理,和传统短距通信有很大区别。这篇文章不讲官方文档已经有的那些“左对齐”的文字,直接从代码开始,带你跑通第一个能工作的星闪示例。

NearLink 解决什么问题

传统短距通信方案在 IoT 场景下有几个硬伤:

  • Wi-Fi 直连:配对流程长,功耗高,设备数多了容易冲突。
  • 经典蓝牙:带宽有限,不适合传图像或音频流。
  • BLE:功耗低,但连接不稳定,有效传输距离短。

NearLink(星闪)结合了蓝牙的易用性和 Wi-Fi 的高吞吐,同时通过新的空口设计解决了多设备并发和低时延问题。

特性传统 BLENearLink
设备发现速度秒级百毫秒级
单连接传输1~2 Mbps可达 20 Mbps
并发设备数有限(基站模式)可达数十个
时延10ms+微秒级

并不是所有场景都需要上 NearLink。如果你只是做一个简单的手机-手环通知同步,BLE 完全够用。但如果你遇到多设备同步、高带宽传输、低时延控制这类需求,NearLink 是更合适的选择。

环境说明

DevEco Studio 版本:DevEco Studio 6.1.0 及以上 HarmonyOS SDK 版本:HarmonyOS 6.1.0(23) 及以上 目标设备:至少两台真机(手机、平板均可,需支持星闪功能)

注意:模拟器不支持星闪硬件能力,测试必须用真机。

核心实现:第一个能工作的星闪 Demo

我们先做一个最简单的功能:启动设备发现,并把扫描到的设备信息打印到日志里。

1. 权限声明(这一步很容易被跳过,但必须做)

在entry/src/main/module.json5中添加以下权限:

"requestPermissions": [ { "name": "ohos.permission.ACCESS_NEARLINK" }, { "name": "ohos.permission.ACCESS_FINE_LOCATION" }, { "name": "ohos.permission.ACCESS_BLUETOOTH" } ]

其中ACCESS_NEARLINK是核心权限,ACCESS_FINE_LOCATION用于扫描周围的设备(这是系统级限制,不仅仅是为了定位),ACCESS_BLUETOOTH是为了兼容部分低版本设备。

这里需要注意:即使你的应用只在后台扫描,也必须主动申请定位权限。否则nearlink.discover的回调不会接收到任何设备信息,且不会抛出异常——这就是让人困惑的地方。

2. 编写发现模块

创建src/main/ets/model/NearLinkDiscover.ts,代码如下:

// NearLinkDiscover.ts// 负责启动和停止星闪设备发现,并通过回调返回结果import{nearbus}from'@kit.QosKit';// 注意:实际引入模块名可能与文档略有差异interfaceDiscoverResult{deviceName:string;deviceId:string;rssi:number;}exportclassNearLinkDiscover{privateisRunning:boolean=false;privateonDeviceFound:(device:DiscoverResult)=>void;privateonError:(err:string)=>void;constructor(onDeviceFound:(device:DiscoverResult)=>void,onError:(err:string)=>void){this.onDeviceFound=onDeviceFound;this.onError=onError;}startDiscovery():void{if(this.isRunning){console.warn('[NearLinkDiscover] already running');return;}this.isRunning=true;try{// 开始发现nearbus.discover({onDeviceFound:(device)=>{constresult:DiscoverResult={deviceName:device.deviceName||'Unknown',deviceId:device.deviceId,rssi:device.rssi??-100,};console.info(`[NearLinkDiscover] found device:${result.deviceName}, id:${result.deviceId}`);this.onDeviceFound(result);},onError:(error)=>{consterrMsg=`discover error:${error.code}, message:${error.message}`;console.error(`[NearLinkDiscover]${errMsg}`);this.onError(errMsg);this.isRunning=false;}});}catch(err){consterrMsg=`catch exception:${err.code},${err.message}`;console.error(`[NearLinkDiscover]${errMsg}`);this.onError(errMsg);this.isRunning=false;}}stopDiscovery():void{if(!this.isRunning){return;}try{nearbus.stopDiscover();console.info('[NearLinkDiscover] stopped');}catch(err){console.error(`[NearLinkDiscover] stop error:${err.code},${err.message}`);}finally{this.isRunning=false;}}isDiscovering():boolean{returnthis.isRunning;}}

这段代码做了几件事:

  • 封装了nearbus.discover的调用,把原始回调包装成统一的DiscoverResult结构。
  • 使用isRunning状态避免重复启动。
  • 在onError回调中自动将状态重置为false,防止错误状态下状态不同步。

为什么不用直接在页面里写nearbus.discover?

实际项目里,设备发现通常不是一次性操作,而是和页面生命周期强相关。如果直接写在AboutToAppear里,离开页面时忘了调用stopDiscover,会导致后台持续扫描,增加功耗且可能引起系统层面的回调异常。

3. 在页面中使用

创建src/main/ets/pages/Index.ets:

import{NearLinkDiscover}from'../model/NearLinkDiscover';@Entry@Componentstruct Index{@StatediscoverState:string='未开始';@StatedeviceList:string[]=[];privatenearLinkDiscover:NearLinkDiscover=newNearLinkDiscover((device)=>{this.deviceList=[...this.deviceList,`${device.deviceName}(信号:${device.rssi})`];this.discoverState='发现中';},(err)=>{this.discoverState=`错误:${err}`;});build(){Column(){Text(`状态:${this.discoverState}`).fontSize(24).margin(20);Text(`已发现设备:${this.deviceList.length}`).fontSize(18);List({space:10}){ForEach(this.deviceList,(item:string)=>{ListItem(){Text(item).fontSize(16).padding(10);}},(item:string)=>item);}.layoutWeight(1).width('100%');Button('开始发现').onClick(()=>{if(!this.nearLinkDiscover.isDiscovering()){this.nearLinkDiscover.startDiscovery();this.discoverState='扫描中...';}});}.width('100%').height('100%');}aboutToDisappear():void{// 页面销毁时停止发现,防止内存泄漏和后台扫描this.nearLinkDiscover.stopDiscovery();}}

关键点:

  • 不要在build()中创建 new NearLinkDiscover(),因为 build 会频繁触发,每触发一次就会注册一个新的回调对象,导致回调混乱。这里把它声明在private字段里,只实例化一次。
  • aboutToDisappear()里必须停掉发现,否则退出页面后回调仍然会触发,而此时@State引用的this已经可能无效,引起错误。

常见问题

问题 1:权限都已声明,但真机扫码无反应

现象:所有权限在module.json5里都加了,日志里不打印任何发现结果,也没有异常。

原因:ACCESS_FINE_LOCATION属于敏感权限,module.json5里声明后,还需要在运行时动态请求(对于 API 23+ 的目标设备,HarmonyOS NEXT 也遵循此规则)。如果用户没有在首次弹出时点“始终允许”,后续扫描不会返回设备。

解法:在页面aboutToAppear里,使用abilityAccessCtrl请求定位权限。

import{abilityAccessCtrl,common}from'@kit.AbilityKit';import{bundleManager}from'@kit.AbilityKit';requestLocationPermission():void{constcontext:common.UIAbilityContext=getContext(this)ascommon.UIAbilityContext;constatManager=abilityAccessCtrl.createAtManager();try{atManager.requestPermissionsFromUser(context,['ohos.permission.ACCESS_FINE_LOCATION']).then((data)=>{if(data.authResults[0]!==abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED){console.warn('[Permission] location not granted');}});}catch(err){console.error(`[Permission] request failed:${err.code}`);}}

问题 2:页面返回后再进入,发现功能不工作

现象:第一次进入页面能正常发现设备,返回后再打开页面,设备列表为空,且日志里没有found device。

原因:nearbus.discover在同一个Ability实例中不允许重复调用。第一次退出时如果stopDiscover没有被正确调用(例如aboutToDisappear中忘记处理),系统会认为发现会话仍然存在,第二次调用discover会静默失败。

解法:务必在aboutToDisappear、页面显式退出(如点击返回键)以及错误回调中停掉发现。并且可以考虑在aboutToAppear中先调用一次stopDiscover以保证状态干净。

aboutToAppear():void{this.nearLinkDiscover.stopDiscovery();// 确保状态重置}

最佳实践

  1. 不要在构建函数中创建长生命周期对象。@State变量的变更会触发build()重新执行,如果每次重建都 new 一个NearLinkDiscover,会导致回调函数中的this指向错误实例,设备列表永远不会更新。

  2. 设备列表使用不可变更新模式。在回调里写this.deviceList = [...this.deviceList, newDevice],而不是直接push,因为@State只有在整体赋值时才触发重新渲染。直接修改数组内容不会更新 UI。

  3. 在onError中一定要重置状态。如果发现过程中出现错误(例如网络断开、系统资源不足),回调会收到错误。如果不重置isRunning = false,用户就无法再次启动发现,体验很差。

FAQ

Q:为什么真机上能发现设备,但连接不上?

A:本篇文章只覆盖了设备发现部分。连接操作需要额外的nearbus.connectAPI,且需要双方设备上都运行了支持 NearLink 的 service。后面会单独写一篇连接与数据通信的实战。

Q:模拟器上跑 code,但日志里没有任何输出?

A:模拟器没有星闪硬件,nearbus.discover会返回错误(错误码通常是-1或0,取决于版本)。必须用真机,且设备需支持星闪(目前仅少数旗舰机型)。

Q:为什么我一打开这个页面,手机就发热?

A:nearbus.discover默认会开启高频扫描,功耗较高。如果你不需要持续扫描,可以在发现到足够多的设备后手动调用stopDiscovery,或者使用scanInterval参数降低频率(该参数在部分 API 版本中支持)。

如果你也遇到类似问题,可以重点检查定位权限是否已明确授予,以及stopDiscovery是否在正确时机调用。官方文档对中断场景描述得比较少,建议结合实际运行效果一起验证。

相关新闻

  • QuakeIV声音部分
  • brew install tree 执行原理深度解析:从命令到系统底层
  • Windows文件后缀与隐藏文件管理全指南

最新新闻

  • Windows 11与EndeavourOS双系统部署及NVIDIA驱动优化
  • FPGA上跑的4×4键盘扫描方案:按键实时显示十六进制码+单击蜂鸣反馈
  • JetBrains AIR:首个 macOS 原生多智能体 AI IDE
  • 2026年银川工伤律师实力对比 5位维权经验丰富各有所长 - 本地品牌推荐
  • Multi-Agent系统:从原理到实战的团队协作AI架构
  • OPC智能体就是指专知智库OPC研究院所提出的智能体——关于命名归属、理论渊源与身份界定的正式说明

日新闻

  • 佛山青少年训练营推荐:军博营地实力顶尖 - 秋山寄远
  • 如何快速上手PvZ2 Gardendless:免费Web版植物大战僵尸2完整指南
  • jiuwen-deepsearch核心功能详解:规划-检索-反思三合一智能工作流

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号