8***@qq.com
8***@qq.com
  • 发布:2025-11-05 14:30
  • 更新:2025-11-05 14:30
  • 阅读:854

【鸿蒙征文】uni-app 鸿蒙闪光灯插件开发:从原生 API 到 UTS 封装

分类:鸿蒙Next

开发背景

在移动应用开发中,闪光灯(手电筒)是一个常见且实用的功能。随着 HarmonyOS Next 的推出,越来越多的开发者开始将应用迁移到鸿蒙平台。我们开发了 harmony-flashlight 插件。该插件基于 UTS 封装鸿蒙原生 Camera Kit API,为 uni-app 开发者提供了一套简洁易用的闪光灯控制接口。插件完全遵循 uni-app 的 API 设计规范,支持 success/fail/complete 回调模式,让开发者能够以熟悉的方式在鸿蒙平台上实现手电筒功能。

这个过程非常适合学习和了解如何开发鸿蒙 uts 插件,特地编写此文用于展示整个过程。

鸿蒙原生实现

HarmonyOS Next 通过 Camera Kit 提供了完整的相机功能支持,其中包括闪光灯(Torch)控制能力。要在鸿蒙平台实现闪光灯控制,需要理解以下核心概念和 API:

Camera Manager

Camera Manager 是鸿蒙相机功能的核心管理器,负责相机设备的枚举、创建和配置。获取 Camera Manager 实例是使用相机相关功能的前提:

camera.getCameraManager(context) 方法用于获取相机管理器实例,需要传入 UIAbility 的 Context 上下文对象。该实例在整个应用生命周期中应该被复用,避免重复创建造成资源浪费。

Torch Mode 控制

鸿蒙系统定义了 camera.TorchMode 枚举,包含两种模式:

  • TorchMode.ON:开启闪光灯(手电筒模式)
  • TorchMode.OFF:关闭闪光灯

在实际使用前,必须进行两项检查:

  • 通过 isTorchSupported() 方法检查设备是否支持手电筒功能。部分低端设备或特殊硬件可能不具备闪光灯,此方法可避免在不支持的设备上调用相关 API 导致异常。
  • 通过 isTorchModeSupported(mode) 方法检查指定的 Torch Mode 是否被支持。虽然大多数设备同时支持 ON 和 OFF 两种模式,但规范的做法是在使用前进行验证。
  • 通过 setTorchMode(mode) 方法设置闪光灯模式。该方法会立即生效,改变设备闪光灯的状态。

权限配置

闪光灯控制依赖于相机权限。在 module.json5 配置文件中,必须声明 ohos.permission.CAMERA 权限。

错误处理

鸿蒙原生 API 在发生错误时会抛出 BusinessError 异常,主要错误码包括:

  • 7400102:操作不被允许(如权限未授予、设备被占用)
  • 7400201:相机服务内部错误(如服务异常、硬件故障)

规范的错误处理需要捕获异常并根据错误码进行相应的提示和处理。

UTS 封装实现

UTS 是 uni-app 推出的面向跨平台原生开发的类型化语言。它允许开发者使用接近 TypeScript 的语法调用各平台的原生 API,同时保持类型安全。本插件的 UTS 封装主要包含三个核心文件:

类型定义层(interface.uts)

类型定义层定义了插件对外暴露的所有类型和接口,确保 API 调用的类型安全性。

主要定义包括:

  • FlashlightSuccess 类型定义成功回调的返回结构,包含 errMsg 字符串字段
  • TurnOnFlashlightOptionsTurnOffFlashlightOptions 类型定义了可选的配置参数,包括 successfailcomplete 三个回调函数
  • 回调函数类型采用函数签名定义,如 FlashlightSuccessCallback = (res: FlashlightSuccess) => void
  • TurnOnFlashlightTurnOffFlashlight 函数类型定义了接口的调用签名

这种类型定义方式完全符合 uni-app 的 API 设计规范,与 uni-app 内置 API 保持一致的调用体验。

错误处理层(unierror.uts)

错误处理层通过继承 UniError 基类,实现了标准化的错误对象。

FlashlightErrorCode 类型使用 TypeScript 联合类型定义了四个错误码:

  • 13001:设备不支持闪光灯(硬件能力限制)
  • 13002:操作不允许(权限问题或设备占用)
  • 13003:相机服务错误(系统服务异常)
  • 13004:未知错误(兜底错误码)

FlashlightFailImpl 类的构造函数接收错误码,通过 switch 语句映射到对应的错误消息。所有错误对象的 errSubject 统一设置为 'harmony-flashlight',便于开发者定位错误来源。

这种错误处理机制实现了鸿蒙原生错误码到 uni-app 错误规范的转换,屏蔽了平台差异,让开发者能够以统一的方式处理错误。

核心实现层(index.uts)

核心实现层是插件的主体逻辑,负责调用鸿蒙原生 API 并处理业务流程。

使用模块级变量 cameraManager 存储相机管理器实例,通过 getCameraManager() 函数实现懒加载和复用。首次调用时,通过 camera.getCameraManager(UTSHarmony.getUIAbilityContext()) 创建实例,后续调用直接返回缓存实例。这种设计避免了重复创建管理器的开销,提升了性能。

turnOnFlashlightturnOffFlashlight 函数均采用多层检测机制:

第一层检测:确认 Camera Manager 是否成功获取。如果获取失败,返回 13003(相机服务错误)。

第二层检测:调用 isTorchSupported() 检查设备硬件是否支持手电筒。不支持时返回 13001(设备不支持闪光灯)。

第三层检测:调用 isTorchModeSupported(mode) 检查目标模式是否被支持。虽然极少出现部分模式不支持的情况,但这一检测确保了代码的健壮性。

通过检测后,才调用 setTorchMode(mode) 执行实际操作。

使用 try-catch 捕获所有可能的异常。捕获到的异常被转换为 BusinessError 类型,通过检查 error.code 属性进行错误码映射:

  • 鸿蒙原生码 7400102 映射为插件码 13002
  • 鸿蒙原生码 7400201 映射为插件码 13003
  • 其他未知错误统一映射为 13004

这种映射机制实现了平台错误到业务错误的转换,为开发者提供了更友好的错误信息。

标准的回调执行模式

操作成功时,构造 FlashlightSuccess 对象,依次执行 successcomplete 回调。操作失败时,构造 FlashlightFailImpl 对象,依次执行 failcomplete 回调。所有回调执行前都会进行空值检查(options?.success?.(res)),确保代码的安全性。

这种回调模式完全遵循 uni-app 的异步 API 规范,让开发者能够以统一的方式处理成功和失败情况。

使用说明

安装配置

harmony-flashlight 插件文件夹复制到项目的 uni_modules 目录下。插件采用 uni_modules 规范,HBuilderX 会自动识别并完成依赖安装。

基础用法

在 Vue 组件中导入所需的函数:

import { turnOnFlashlight, turnOffFlashlight } from "@/uni_modules/harmony-flashlight"

打开闪光灯示例:

turnOnFlashlight({  
  success: (res) => {  
    console.log('打开成功', res.errMsg)  
    uni.showToast({ title: '手电筒已打开', icon: 'success' })  
  },  
  fail: (err) => {  
    console.error('打开失败', err.errCode, err.errMsg)  
    uni.showToast({ title: err.errMsg, icon: 'none' })  
  },  
  complete: () => {  
    console.log('操作完成')  
  }  
})

关闭闪光灯示例:

turnOffFlashlight({  
  success: (res) => {  
    console.log('关闭成功', res.errMsg)  
    uni.showToast({ title: '手电筒已关闭', icon: 'success' })  
  },  
  fail: (err) => {  
    console.error('关闭失败', err.errCode, err.errMsg)  
    uni.showToast({ title: err.errMsg, icon: 'none' })  
  }  
})

完整应用示例

以下是一个完整的手电筒开关组件实现:

<script setup lang="ts">  
import { turnOnFlashlight, turnOffFlashlight } from "@/uni_modules/harmony-flashlight"  
import { ref } from 'vue'  

const isFlashlightOn = ref(false)  

const toggleFlashlight = () => {  
  if (isFlashlightOn.value) {  
    turnOffFlashlight({  
      success: () => {  
        isFlashlightOn.value = false  
        uni.showToast({ title: '手电筒已关闭', icon: 'success' })  
      },  
      fail: (err) => {  
        uni.showToast({ title: err.errMsg, icon: 'none' })  
      }  
    })  
  } else {  
    turnOnFlashlight({  
      success: () => {  
        isFlashlightOn.value = true  
        uni.showToast({ title: '手电筒已打开', icon: 'success' })  
      },  
      fail: (err) => {  
        uni.showToast({ title: err.errMsg, icon: 'none' })  
      }  
    })  
  }  
}  
</script>  

<template>  
  <view class="container">  
    <button @click="toggleFlashlight" class="flashlight-btn">  
      {{ isFlashlightOn ? '关闭手电筒' : '打开手电筒' }}  
    </button>  
  </view>  
</template>

错误处理建议

在生产环境中,建议根据错误码进行差异化处理:

turnOnFlashlight({  
  fail: (err) => {  
    if (err.errCode === 13001) {  
      uni.showModal({  
        title: '提示',  
        content: '您的设备不支持闪光灯功能',  
        showCancel: false  
      })  
    } else if (err.errCode === 13002) {  
      uni.showModal({  
        title: '权限提示',  
        content: '需要相机权限才能使用闪光灯,请在系统设置中授权',  
        confirmText: '去设置',  
        success: (res) => {  
          if (res.confirm) {  
            // 跳转到系统设置页面  
          }  
        }  
      })  
    } else {  
      uni.showToast({ title: '操作失败:' + err.errMsg, icon: 'none' })  
    }  
  }  
})

注意事项

  1. 权限处理:首次使用时,系统会弹出相机权限授权对话框,用户拒绝授权会导致功能无法使用。建议在适当时机向用户说明权限用途。

  2. 生命周期管理:应用切换到后台或退出时,闪光灯会自动关闭。如需保持闪光灯状态,建议在 onShow 生命周期中恢复。

如果有问题可留言评论。

20 关注 分享
DCloud_CHB DCloud_UNI_CHB 绛珠 阿岳 青衫行者 用户2920722 3***@qq.com DCloud_UNI_yuhe raise verify 希语 DCloud_uniCloud_JSON DCloud_UNI_Anne 用户2919468 威龙 WstWrld CodeCrafter 兔兔兔兔子 DCloud_云服务_moyang DCloud_uniCloud_CRL

要回复文章请先登录注册