React Native for OpenHarmony 实战:三方库 react-native-torch 的鸿蒙化适配指南
本文记录把 react-native-torch(手电筒 / 相机闪光灯控制)适配到 HarmonyOS 的完整过程,包括版本对齐、原生实现走查、接入宿主、构建运行,以及依赖硬件的库在模拟器上到底该怎么验证。
react-native-torch 的 API 只有两个,却是个典型例子:它控制的是一块模拟器上根本不存在的硬件。这种库的适配难点不在代码量,而在"什么算验证通过"。

一、先说结论
| 项 | 结果 |
|---|---|
| 上游最新版 | 1.2.0 |
| 是否带原生实现 | 是(ArkTS TurboModule,不是纯 JS) |
| 是否依赖硬件 | 是,依赖相机闪光灯 |
| 公开 API | switchState(enabled)、requestCameraPermission(title?, message?),都返回 Promise |
| 是否需要声明权限 | 不需要(连 ohos.permission.CAMERA 都不用) |
| 原生实现体量 | ArkTS 侧 19 行,HAR 包 2,875 字节 |
| 编译是否通过 | ✅ assembleHap 成功,HAP 从 80,714,316 增至 80,867,227 字节(+152,911 ≈ 149 KB) |
| 原生是否注册 | ✅ 日志 TM created: RCTTorch |
| 软件层断言 | ✅ 13 / 13 通过(契约 6 + 参数守卫 7) |
| 硬件层结论 | ⚠️ 本机没有闪光灯,四次调用全部以 ERR_TORCH_UNAVAILABLE 拒绝——没有返回 true 假装成功 |
一句话结论:这个库不需要权限、实现只有 19 行、接入后正常注册;但它要控制的闪光灯在这台设备上不存在,所以"灯亮不亮"无法在本轮验证——本轮真正验证到的是它在硬件不支持时会明确报错,而不是假装成功。这两件事必须分开说。
二、判定过程
适配前先回答三个问题。
2.1 这个库需要鸿蒙化吗
看源码就知道必须:
// src/NativeTorch.ts
import type {TurboModule} from 'react-native';
import {TurboModuleRegistry} from 'react-native';
export interface Spec extends TurboModule {
switchState(enabled: boolean): Promise<boolean>;
requestCameraPermission(title?: string, message?: string): Promise<boolean>;
}
export default TurboModuleRegistry.getEnforcing<Spec>('RCTTorch');
getEnforcing 意味着取不到原生模块就直接抛错,没有 JS 兜底实现。而 react-native-torch 上游只提供 Android 与 iOS 原生代码,鸿蒙上没有 RCTTorch 这个名字的模块——所以必须补一个鸿蒙原生实现。
这里和纯 JS 库的分界线很清楚:纯 JS 库只要能跑通就直接可用,这类库不补原生就必然报错。
2.2 上游版本核对
npm view react-native-torch version # 1.2.0
拿到鸿蒙适配包后对比到上游基线,版本一致,没有落后。
2.3 交付包里该有的信息都在
spec.json 里有 upstream 仓库地址,也有 upstreamCommit 基线 commit——两样都记了,意味着后续上游改动时能确定该合到哪个点,这次适配的可追溯性是完整的。
validation 里还明确写了能力边界,其中一条关键:
返回
true不表示设备一定有闪光灯。
交付包自己先把这件事说清楚了,这一点很重要——它没有让调用方误以为"switchState 返回 true = 灯亮了"。
三、适配实现:先查支持性,再下发命令
原生实现全文:
// harmony/torch/src/main/ets/RCTTorchTurboModule.ts
import camera from '@ohos.multimedia.camera';
import { UITurboModule } from '@rnoh/react-native-openharmony/ts';
export class RCTTorchTurboModule extends UITurboModule {
async switchState(enabled: boolean): Promise<boolean> {
const manager = camera.getCameraManager(this.ctx.uiAbilityContext);
const mode = enabled ? camera.TorchMode.ON : camera.TorchMode.OFF;
if (!manager.isTorchSupported() || !manager.isTorchModeSupported(mode)) {
throw new Error('ERR_TORCH_UNAVAILABLE: flashlight mode is not supported');
}
manager.setTorchMode(mode);
return true;
}
async requestCameraPermission(): Promise<boolean> {
// HarmonyOS CameraManager torch APIs do not require CAMERA permission
// or open a camera input.
return true;
}
}
三个设计点值得展开。
3.1 支持性检查必须在下发命令之前
if (!manager.isTorchSupported() || !manager.isTorchModeSupported(mode)) {
throw new Error('ERR_TORCH_UNAVAILABLE: ...');
}
manager.setTorchMode(mode);
这里做了两层检查:
isTorchSupported()—— 这台设备有没有闪光灯;isTorchModeSupported(mode)—— 这个模式(ON / OFF)支不支持。
两层是必要的,因为有些设备的闪光灯只支持常亮、不支持闪烁(或反过来),“有闪光灯"不等于"这个模式可用”。
检查失败时抛的是带前缀的明确错误(ERR_TORCH_UNAVAILABLE),调用方能靠字符串识别并走降级逻辑。这一点比"静默返回 false"好得多——静默失败会让调用方以为操作成功了。
3.2 它不打开相机、不采集图像
实现里出现的相机 API 只有四个:
getCameraManager / isTorchSupported / isTorchModeSupported / setTorchMode
没有 createCameraInput、没有 createCaptureSession、没有预览流。 这是静态就能查清的事实,也是理解"为什么不需要 CAMERA 权限"的钥匙——它只借用 CameraManager 的手电接口,不碰相机采集链路。
3.3 JS 侧的参数守卫是"被拒绝的 Promise"
上游 JS 层保留了类型校验:
async function switchState(enabled: boolean): Promise<boolean> {
if (typeof enabled !== 'boolean') {
throw new TypeError('Torch.switchState expects a boolean');
}
return NativeTorch.switchState(enabled);
}
注意它在 async 函数里,所以抛出的是一个被拒绝的 Promise,不是同步异常。这意味着:
// ❌ 抓不到
try { Torch.switchState(1); } catch (e) {}
// ✅ 这样才抓得到
await Torch.switchState(1).catch(e => console.log(e.message));
这个细节在本轮验证中被实际确认过——参数守卫组的断言必须用 await 才捕获到 TypeError。调用方如果按同步异常来写 try/catch,会漏掉所有参数错误。
四、requestCameraPermission() 为什么直接返回 true
这个方法最容易引起误解。它在 Android 上的语义是弹出系统相机授权框,所以返回值表示"用户授权了没有"。到了鸿蒙,实现直接写成:
async requestCameraPermission(): Promise<boolean> {
return true;
}
为什么可以这样写?
因为鸿蒙的手电筒 API 走的是 CameraManager,既不要求声明 ohos.permission.CAMERA,也不打开相机输入。既然没有权限可申请,也就没有授权框可弹——直接返回 true 表示"没有权限障碍,你继续调 switchState 就行"。
这个 true 的含义要读准:
| 它表示 | 它不表示 |
|---|---|
| 不存在权限障碍 | 设备一定有闪光灯 |
可以继续调用 switchState | 闪光灯能被点亮 |
| 保留了上游接口的兼容性 | Android 上的授权弹窗行为也一致 |
交付包 README 专门写了这个限定,这一点做得很诚实。如果调用方把 requestCameraPermission() === true 当成"硬件可用"的判据,就会在无闪光灯设备上做出错误决策——正确的判据是 switchState 是否成功,而不是权限方法是否返回 true。
五、接入宿主
宿主工程是一个已经运行起来的 RNOH 示例应用。接入这个库要改四处:
| 文件 | 改动 |
|---|---|
package.json | 加 "react-native-torch": "file:../react-native-torch" |
metro.config.js | watchFolders 增加该库的绝对路径 |
index.js | import 测试页并注册 |
harmony/entry/oh-package.json5 | 手工加 HAR 依赖 |
第四处是唯一需要留神的:
"@react-native-ohos/react-native-torch": "file:../../node_modules/react-native-torch/harmony/torch.har"
自动链接工具不会写这一处。 它会把 package.json 的依赖关系和 Metro 的模块解析处理好,日志里也会报 linked 9 libraries,但模块级的 oh-package.json5 依赖需要手工补——漏了这一步,编译期就会在 CMake / ohpm 阶段报找不到包。
这一点交付包的 README 里也专门提醒了,写成了一句很实在的话:
若宿主 CMake 的
OH_MODULES_DIR指向entry/oh_modules,还需在harmony/entry/oh-package.json5添加 HAR 依赖……不能据 link 成功省略这一步。
这类"工具链不会代劳的一步"是接入环节最容易踩的坑:link-harmony 成功不代表接线完成,得认准编译产物里到底有没有这个包。
另一个刻意的选择:没有改 harmony/entry/src/main/module.json5。 宿主的 requestPermissions 里只有:
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" },
{ "name": "ohos.permission.VIBRATE" }
]
没有 ohos.permission.CAMERA——保持原样,因为本库不需要。这一点后来还成了一个有用的旁证,见第七节。
关于换测试页
宿主用一个启动参数(rnAppKey)决定加载哪个测试页。这个参数只在冷启动时生效,所以换页必须:
hdc shell aa force-stop com.rnoh084.demo
hdc shell aa start -b com.rnoh084.demo -a EntryAbility --ps rnAppKey TorchTestApp
force-stop 不能省。 少了它,应用还活着,新参数不会重新读取,你会一直在看旧页面——而且页面长得没错,很容易误判。
六、构建与运行
# 1. 装依赖
npm install
# 2. 自动链接
node_modules\.bin\react-native link-harmony # linked 9 libraries
# 3. 装 HAR(在 harmony/ 目录)
ohpm install --all
# 4. 出 bundle
npm run dev
# 5. 打 HAP
hvigorw --mode module -p product=default -p module=entry@default assembleHap --no-daemon
编译结果:
| 项 | 数值 |
|---|---|
首次 assembleHap 耗时 | 6 分 39 秒 |
| HAP 变化 | 80,714,316 → 80,867,227 字节(+152,911 ≈ 149 KB) |
| 原生注册日志 | #RNOH_ARK ... TM created: RCTTorch |
| 二次重编(改了一条断言) | 6 分 27 秒,HAP 80,867,224 字节 |
两个数量级上的观察:
- 149 KB vs 2,875 字节的 HAR:HAR 本身极小,但会连带拉起相机相关的能力声明与依赖,所以最终产物增量比 HAR 大两个数量级。别拿 HAR 体积估增量。
- 编译耗时基本由 ABI / CMake 阶段决定,跟这个库没关系:加 19 行 ArkTS 不会让编译从 2 分钟变 6 分钟,这 6 分钟是 RNOH 工程本身的量级,做集成排期时要按这个数留时间。
日志里的 #RNOH_ARK 标签说明这是 ArkTS 侧 TurboModule(不是纯 C++ TurboModule,也不是 JSI)。这个区别在排查时有用:ArkTS 模块的问题看 ArkTS 日志,纯 C++ 模块才有 #RNOH_CPP 的 TurboModuleFactory.cpp 记录。
七、验证设计:依赖硬件的库在模拟器上怎么验
这是本文最重要的一节。
7.1 问题:灯亮不亮,模拟器答不了
模拟器(Pura X View,ohos-x64)没有闪光灯硬件。这意味着一件事:
switchState(true)之后"灯是否真的亮了",在模拟器上永远无法验证。
如果验证方案写成"调用 switchState(true),断言返回 true",那么在这个环境下必然失败——但这个失败不是库的问题。反过来,如果为了让测试通过而放宽断言,又会遮盖真正该测的东西。
所以验证设计的关键是换一个落点。
7.2 换落点:从"硬件是否动作"换到"行为是否正确"
既然"能不能亮"验不了,那就验能验的、而且同样重要的:
硬件不支持时,它是明确失败,还是返回
true假装成功?
这个问题在模拟器上完全可以验证,而且它比"灯能不能亮"更接近库的真实质量——因为调用方写降级逻辑时,依赖的正是"失败能被感知到"这件事。一个在无硬件时静默返回 true 的库,会让调用方以为灯亮了,这比报错糟糕得多。
于是把验证分成三层:
| 层 | 能验吗 | 内容 |
|---|---|---|
| A. 契约与类型 | ✅ 完全可验 | 两个方法存在、返回 Promise、权限方法解析为 true |
| B. JS 侧参数守卫 | ✅ 完全可验 | 非布尔参数必须以 TypeError 拒绝(6 种取值) |
| C. 硬件相关行为 | ⚠️ 只记录,不断言"应当成功" | 实测结局,重点看是明确失败还是假装成功 |
A、B 两层进通过率,C 层如实记录。 这样通过率是有意义的(13 / 13),同时不掩盖硬件未验证的事实。
7.3 A 组:契约与类型(6 项,全通过)
| 断言 | 结果 |
|---|---|
switchState 是 function | ✅ |
requestCameraPermission 是 function | ✅ |
requestCameraPermission() 返回 Promise | ✅ |
requestCameraPermission() 解析为 true | ✅ |
switchState(true) 返回 Promise | ✅ |
switchState(false) 返回 Promise | ✅ |
这里有个细节让这组在无硬件时依然成立:switchState 是 async 函数,无论内部成功还是抛错,返回的一定是 Promise。 所以"返回 Promise"这条断言与硬件无关,可以放心验。
7.4 B 组:参数守卫(7 项,全通过)
非布尔参数必须以 TypeError 拒绝:
| 传入值 | 结果 |
|---|---|
undefined | ✅ TypeError |
null | ✅ TypeError |
0 | ✅ TypeError |
1 | ✅ TypeError |
"true" | ✅ TypeError |
{} | ✅ TypeError |
| 非法参数之后,合法调用不再被参数守卫拦住 | ✅ |
最后一条值得单独说,因为它让我改过一次断言。
初版我把它写成"非法参数之后调用应当成功"。结果在本机失败——因为无闪光灯时,合法调用会以 ERR_TORCH_UNAVAILABLE 拒绝。那是正确的硬件行为,不是参数问题,但我的断言把两件事混在了一起。
改判据后:只检查结果里不再出现 TypeError,不管它最终是成功还是因硬件拒绝——这样断言只依赖"参数守卫"这一个契约,与环境能力无关。
教训:测试断言不能隐含"环境具备某能力"这个前提。
断言应该只依赖被测代码的契约,不依赖环境能力。如果确实要断言环境,就把它单独成组并如实记录,而不是混进通过率里——否则通过率会随设备变化,失去意义。
7.5 C 组:硬件相关行为(如实记录)
四次调用的实测结果:
硬件|switchState(true) 拒绝:ERR_TORCH_UNAVAILABLE: flashlight mode is not supported
硬件|switchState(false) 拒绝:ERR_TORCH_UNAVAILABLE: flashlight mode is not supported
硬件|switchState(true) 第二次 拒绝:ERR_TORCH_UNAVAILABLE: flashlight mode is not supported
硬件|switchState(false) 第二次 拒绝:ERR_TORCH_UNAVAILABLE: flashlight mode is not supported
硬件|两轮结果是否一致:是
硬件|四次调用是否都以 ERR_TORCH_UNAVAILABLE 拒绝:是
硬件|硬件不支持时是否返回 true 假装成功:否(明确失败)
后两条是页面从实测结果动态推导出来的,不是写死的文案——这样它们才是断言,而不是修饰。
两个结论:
- 本机确实没有闪光灯 —— 四次调用全部走到"不支持"分支,两轮一致;
- 库的行为是对的 —— 硬件不支持时明确拒绝,没有返回
true假装成功。
第 2 条才是本轮真正验证到的东西,而它恰好是模拟器能验、也最该验的那一条。

7.6 两个独立旁证
断言之外还找了两个不依赖测试页的旁证,用来交叉验证"确实没碰硬件"。
旁证一:相机服务侧没有任何日志。
在两次调用前后抓 hilog,没有相机服务的任何记录。这和代码路径完全一致:isTorchSupported() 检查失败就抛错了,从未执行到 setTorchMode,所以系统侧没有动作可记。
如果代码是"先下发命令再检查结果",就会看到系统侧有响应——日志的有无,正好反证了检查发生在命令之前。
旁证二:没有 CAMERA 权限,错误类型却是"硬件不支持"。
宿主 module.json5 里没有声明 ohos.permission.CAMERA,而 switchState 返回的是:
ERR_TORCH_UNAVAILABLE: flashlight mode is not supported
是"不支持",不是"无权限"。 如果是权限问题,报错应该是权限拒绝;既然系统先给出了硬件不支持的判断,就说明这条调用路径根本没走到权限校验——独立印证了"鸿蒙手电 API 不需要相机权限"这个结论。
这两个旁证的价值在于:它们不来自我的测试代码。 一个来自系统日志,一个来自工程配置,都是外部事实。
7.7 关于测试页本身
测试页沿用了一个统一的断言夹具:每条断言用 record(组名, 描述, 期望, 实际) 记录,最后按组汇总"通过 / 失败"。硬件行为单独成组,不进通过率。页面根节点包在 SafeAreaView 里避免被状态栏遮挡,日志统一带 [torch-test] 前缀方便过滤。
另外,C 组的两个推导结论是运行时算出来的:
四次调用是否都以 ERR_TORCH_UNAVAILABLE 拒绝:是
硬件不支持时是否返回 true 假装成功:否(明确失败)
这样做的好处是——换一台有闪光灯的设备跑,这两行会自动变成"否"和"不适用",而不会继续打印"是"。 写死的文案会骗人,动态推导不会。
八、真机验证:哪些验过了,哪些没验
这一节必须写清楚,因为这是本轮最容易被含糊过去的地方。
8.1 已验证
| 项 | 证据 |
|---|---|
| 两个方法的契约与类型 | A 组 6 条断言全通过 |
| JS 侧参数守卫(6 种非布尔值) | B 组 7 条断言全通过 |
| 原生模块成功注册 | hilog 中 TM created: RCTTorch |
| 模块是 ArkTS 实现 | 日志标签为 #RNOH_ARK |
| 硬件不支持时的失败模式 | C 组:四次调用全部以 ERR_TORCH_UNAVAILABLE 明确拒绝,未返回 true 假装成功,两轮一致 |
| 失败发生命令下发之前 | 相机服务侧无任何 hilog 记录 |
手电 API 不需要 CAMERA 权限 | 宿主无该权限声明,错误类型仍是"硬件不支持"而非"无权限" |
| 编译与产物 | assembleHap 成功,HAP +149 KB |
8.2 未验证(本轮无法验证)
| 项 | 为什么没验 |
|---|---|
| 闪光灯是否真的会亮 | 本机没有闪光灯硬件,无法验证 |
| 开启 / 关闭的实际硬件状态 | 需要真机,并需要看系统侧的手电状态事件 |
| 相机被其他应用占用时的失败路径 | 需要真实硬件与占用场景 |
| 其他 ROM / 平板 / 无闪光灯真机的差异 | 只有一台模拟器 |
| 亮灯时的功耗与发热 | 无硬件 |
8.3 为什么要分开写
因为这两类事的可信度完全不同。
- 把"已验证"说成"适配成功、功能正常"是过度声明——灯到底亮不亮,我没验过;
- 把"未验证"含糊成"应该没问题",会让下一位使用者踩坑;
- 反过来,把"硬件不支持时正确报错"也归入未验证,又低估了本轮的实际成果。
准确的表述是:软件层全通过,硬件动作未验证,但硬件不支持时的失败模式已确认为正确。
九、已知限制
- 模拟器没有闪光灯,"点亮"无法验证。 这是本轮最大的空白,需要真机补充。
requestCameraPermission()恒返回true,是兼容桩而非硬件探测。 它的返回值不能当作"硬件可用"的判据。调用方应改用switchState是否成功来判断。- 无权限声明的结论只在本轮环境成立。 本轮验证了"不声明
CAMERA权限也能走到硬件检查",但没有验证其他 ROM 上是否同样如此。 - 未做跨平台对照。 本轮只验证鸿蒙,没有对比 Android / iOS 上同一接口的行为差异(特别是
requestCameraPermission的弹窗语义)。 ERR_TORCH_UNAVAILABLE是字符串前缀,不是错误码。 调用方靠自己匹配字符串来识别,匹配时要考虑前缀而非全等,否则错误文案微调就会破坏降级逻辑。- 单设备、单次运行。 只在一台模拟器上跑过,没有压力测试、没有并发调用场景、没有反复快速切换。
- 未改动库代码,也未发现缺陷。 本轮唯一一次失败是我自己测试页的断言写错了(隐含了"硬件存在"的前提),修正后通过。
十、常见问题
Q1:调用 switchState(true) 报 ERR_TORCH_UNAVAILABLE,是适配坏了吗?
不一定。先确认设备有没有闪光灯——模拟器上、平板上、很多无闪光灯设备上,这个错误是正确行为。这个库的设计就是"没有闪光灯就明确报错",而不是静默成功。
Q2:requestCameraPermission() 返回 true 了,为什么 switchState 还是失败?
因为这两件事无关。true 表示"不存在权限障碍",不表示设备有闪光灯。在鸿蒙上手电 API 根本不需要相机权限,所以这个方法只是个兼容桩。
Q3:需要声明 ohos.permission.CAMERA 吗?
本库不需要,本轮实测没有声明也能正常走到硬件检查。但如果你的应用自己还要做拍照、录像,那当然要声明——那是另一条采集链路的事。
Q4:为什么 try { Torch.switchState(1) } catch {} 抓不到参数错误?
因为 JS 守卫在 async 函数里,抛出的是被拒绝的 Promise。必须 await 或 .catch():
await Torch.switchState(1).catch(e => console.log(e.message));
Q5:link-harmony 报链接成功,编译还是找不到包?
检查 harmony/entry/oh-package.json5 有没有手工加上 HAR 依赖。自动链接工具不写模块级的这一处,漏了就报找不到包——这不是链接失败,是链接没覆盖到这里。
Q6:换了测试页代码,界面还是旧的?
rnAppKey 这类启动参数只在冷启动生效。先 aa force-stop 再 aa start,否则一直在看旧页面。
Q7:怎么在自己设备上确认闪光灯到底能不能用?
别信权限方法,直接试:
try {
await Torch.switchState(true);
console.log('下发成功'); // 注意:命令被接受,不代表灯一定亮了
} catch (e) {
console.log('不可用:', e.message);
}
注意日志里的措辞——即使返回成功,也只表示"命令被系统接受";要确认灯真的亮了,得看设备本身。这个区分在交付包的 README 里也写明了。
Q8:编译要 6 分多钟,是不是这个库太重?
不是。这 6 分钟是 RNOH 工程本身 ABI / CMake 阶段的量级,跟 19 行 ArkTS 无关。HAR 只有 2,875 字节,但最终 HAP 增了 149 KB——别拿 HAR 体积估集成增量。
小结
react-native-torch 是个小库:两个 API、19 行原生实现、不需要任何权限。但它在方法论上给了一个很典型的题目——当库依赖的硬件在你手上不存在时,验证该怎么做?
这次的做法是:
- 把验证分层。 契约与参数守卫(A、B)完全可验,进通过率;硬件行为(C)只记录、不断言"应当成功"。
- 换验证落点。 既然"灯亮不亮"验不了,就验**“硬件不支持时是否明确失败,而不是返回
true假装成功”**——这一条模拟器能验,而且比"能不能亮"更接近库的质量。 - 找不依赖测试代码的旁证。 相机服务无日志(证明检查发生在命令下发之前)、无
CAMERA权限却报"硬件不支持"(证明这条路径不需要相机权限)——两个都来自系统日志和工程配置,不是我自己的断言。 - 把"已验证"和"未验证"分开写。 软件层全通过是真的,硬件动作没验也是真的,不能混成一句"适配成功"。
另外两条从实践中来的经验:
- 断言不能隐含"环境具备某能力"。 我初版把"非法参数之后调用应当成功"写成断言,在有闪光灯的机器上会过,在这台机器上必然失败。断言只该依赖被测代码的契约,否则通过率会随设备漂移,失去意义。
requestCameraPermission()返回true不是硬件探针。 它是权限语义上的"没有障碍",把两者混为一谈,就会在无硬件设备上做出错误决策。
还有一点关于交付包:它自己在 README 里就写清了"返回 true 不表示设备一定有闪光灯",并且诚实声明了哪些场景是 mock 验证、哪些没做真机覆盖。 一个交付包能主动划出自己的能力边界,比它多写几个 API 有用得多——因为使用者正是靠这句话避免误判的。

本篇用到的库
| 库 | 版本 | 说明 |
|---|---|---|
react-native-torch | 1.2.0 | 手电筒 / 闪光灯控制,本文适配对象。上游仓库 ludo/react-native-torch |
接入方式:
// harmony/entry/oh-package.json5(需手工添加)
"@react-native-ohos/react-native-torch": "file:../../node_modules/react-native-torch/harmony/torch.har"
import Torch from 'react-native-torch';
await Torch.requestCameraPermission(); // 鸿蒙上恒为 true,仅表"无权限障碍"
try {
await Torch.switchState(true); // 成功只代表命令被系统接受
} catch (e) {
// 无闪光灯设备会抛 ERR_TORCH_UNAVAILABLE
console.log(String(e));
}
await Torch.switchState(false);
# 换页启动测试页(force-stop 不能省,换页参数只在冷启动生效)
hdc shell aa force-stop com.rnoh084.demo
hdc shell aa start -b com.rnoh084.demo -a EntryAbility --ps rnAppKey TorchTestApp
验证环境
| 项 | 版本 |
|---|---|
| React Native | 0.84.1 |
| React | 19.2.3 |
| RNOH(npm / ohpm) | @react-native-oh/react-native-harmony / @rnoh/react-native-openharmony 0.84.3 |
| Node.js | v24.14.0 |
| DevEco Studio | 26.0.0.621 |
| HarmonyOS SDK | API 26(26.0.0.32) |
| 设备 | HarmonyOS 7.0.0(26.0.0) Beta2 模拟器 Pura X View(ohos-x64)——无闪光灯硬件 |
| 宿主 HAP 产物 | entry-default-signed.hap(80.87 MB) |
| 本次增量构建 | assembleHap 6 分 39 秒,HAP +149 KB |
| 验证规模 | 设备侧软件层 13 项断言全部通过;硬件行为组 4 次调用如实记录(全部 ERR_TORCH_UNAVAILABLE) |
欢迎加入 CPF-RN 鸿蒙社区:https://atomgit.com/CPF-RN
React Native for OpenHarmony 组织:https://atomgit.com/oh-react-native
RN 三方库鸿蒙适配清单:https://atomgit.com/oh-react-native/rn-ohos-adaptation-overview
更多推荐




所有评论(0)