全部学科
Python全栈
python
NodeJS全栈
nodejs

uni-app 鸿蒙 App 震动失效:ohos.permission.VIBRATE 权限配置全攻略

📅 2026-07-20 uni-app HarmonyOS 鸿蒙 VIBRATE 权限

uni-app 鸿蒙 App 震动失效:ohos.permission.VIBRATE 权限配置全攻略

项目:Vue 3 + uni-app 3.0 App,编译目标 HarmonyOS App
环境:HBuilderX 5.x + DevEco Studio 5.0 + 鸿蒙真机


一、故障现象

做错题时理论上应该触发震动反馈(uni.vibrateLong()),但鸿蒙真机上完全没有任何震动。同样的设备上,微信小程序端的震动是正常的。

代码里有多处震动调用,答错题时触发:

JavaScript
// 答错时震动反馈
if (!isCorrect && settingStore.setting.enableVibrateFeedback) {
  uni.vibrateLong()
}

二、排查过程

2.1 第一次尝试:manifest.json 里加 requestPermissions

对比 Android 配置,发现 Android 端有 android.permission.VIBRATE,而鸿蒙端 app-harmony.distribute 下只有图标配置:

JSON
// manifest.json
"app-harmony": {
    "distribute": {
        "icons": { ... }  // 只有图标,没有权限
    }
}

于是仿照 Android 格式添加:

JSON
"app-harmony": {
    "distribute": {
        "requestPermissions": [
            { "name": "ohos.permission.INTERNET" },
            {
                "name": "ohos.permission.VIBRATE",
                "reason": "用于答错题目时震动反馈及考试倒计时提醒",
                "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
            }
        ],
        "icons": { ... }
    }
}

结果:无效。 构建产物 dist/dev/app-harmony/entry/src/main/module.json5 里依然只有 ohos.permission.INTERNET,VIBRATE 完全没出现。

关键发现:uni-app 的鸿蒙构建系统 不会处理 manifest.jsonapp-harmony.distribute.requestPermissions 这个字段。

2.2 第二次尝试:harmony-permissions UTS 插件

DCloud 官方推荐通过 uni_modules 插件声明鸿蒙权限。于是创建了如下结构:

json5
src/uni_modules/harmony-permissions/
└── utssdk/app-harmony/
    ├── index.uts          ← 插件入口
    ├── module.json5       ← 权限声明
    └── resources/base/element/string.json

module.json5 内容:

TypeScript
{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.VIBRATE" }
    ]
  }
}

结果:无效,还引发新问题。

  • 构建系统没有合并这个子模块的权限
  • index.uts 文件触发了 UTS 编译,提示 Cannot find module: @dcloudio/uni-uts-v1,导致构建直接失败

这条路径彻底走不通。

2.3 第三次排查:深入 native 源码

既然配置层面走不通,回头读运行时实现。在 dist/dev/app-harmony/oh_modules/ 下找到了震动模块的源码:

JavaScript
// VibrateNative.ets(uni-vibrate 鸿蒙实现)
import vibrator from '@ohos.vibrator'

const VIBRATE_ATTRIBUTE: vibrator.VibrateAttribute = {
    usage: 'touch'   // ← 触摸反馈场景
}

static vibrateLong(): number {
    return VibrateNative.startTimeVibration(400)  // 400ms 长震动
}

private static startTimeVibration(duration: number): number {
    try {
        vibrator.startVibration({
            type: 'time',
            duration
        }, VIBRATE_ATTRIBUTE)
        .catch((error) => {
            console.error('startVibration failed', error.code)
        })
        return VIBRATE_SUCCESS   // ← 永远返回成功!
    } catch (error) {
        return VibrateNative.mapErrorCode(error)
    }
}

这里有两个重要发现

  1. usage: 'touch' — 官方文档说这种场景不需要 ohos.permission.VIBRATE。但我们验证了同一台设备、同一系统设置下微信小程序能震动、独立 App 却不能。

  2. 错误被吞没startVibration() 返回 Promise,但函数永远同步返回 VIBRATE_SUCCESS。即使震动失败,.catch 也只是 console.error,JS 侧完全感知不到。

2.4 关键发现:微信为什么能震

微信小程序能震动,是因为小程序运行在微信的容器里。微信作为系统级 App,本身就持有 ohos.permission.VIBRATE。小程序调用 wx.vibrateLong() 时,实际上是微信的 native 层代为执行震动,用的是微信的权限,所以不需要小程序自己声明。

而独立 App 用自己的 bundle identity,即使 usage: 'touch' 理论上不需要权限,在 HarmonyOS 5.0 某些行为下实际仍需在 module.json5 中显式声明


三、最终方案:构建后注入

既然 uni-app 构建不会自动写入 VIBRATE 权限,那就在构建完成后、DevEco Studio 打开前自动注入

3.1 注入脚本

scripts/inject-harmony-permissions.js

batch
const fs = require('fs')
const path = require('path')

const MODULE_JSON5 = path.join(__dirname, '..', 'dist', 'dev', 'app-harmony',
  'entry', 'src', 'main', 'module.json5')

if (!fs.existsSync(MODULE_JSON5)) {
  console.log('[SKIP] module.json5 不存在,跳过权限注入')
  process.exit(0)
}

const json = JSON.parse(fs.readFileSync(MODULE_JSON5, 'utf8'))
json.module.requestPermissions = json.module.requestPermissions || []

const REQUIRED_PERMISSIONS = [
  { name: 'ohos.permission.VIBRATE' }
]

let changed = false
for (const perm of REQUIRED_PERMISSIONS) {
  if (!json.module.requestPermissions.find(p => p.name === perm.name)) {
    json.module.requestPermissions.push(perm)
    console.log('[OK] 已添加 ' + perm.name)
    changed = true
  }
}

if (changed) {
  fs.writeFileSync(MODULE_JSON5, JSON.stringify(json, null, '\t'))
}

3.2 集成到构建流程

dev-harmony.batnpx uni build 之后添加一步:

json5
echo [Step 1.4] 注入鸿蒙权限声明...
node scripts/inject-harmony-permissions.js
if errorlevel 1 (
    echo [WARN] 权限注入失败,继续构建...
)

完整构建流程变为:

text
Step 1:   npx uni build -p app-harmony   ← 生成 module.json5(只有 INTERNET)
Step 1.4: 注入 VIBRATE 权限              ← 自动编辑 module.json5
Step 1.5: 注入图标
Step 1.6: 设置包名
Step 1.7: 重置签名
Step 2:   注入 local.properties
Step 3:   打开 DevEco Studio → Build → Run

3.3 验证

构建后检查 dist/dev/app-harmony/entry/src/main/module.json5

text
{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.INTERNET" },
      { "name": "ohos.permission.VIBRATE" }   // ← 注入成功
    ]
  }
}

控制台输出:

text
[Step 1.4] 注入鸿蒙权限声明...
[OK] 已添加 ohos.permission.VIBRATE

四、失败路径总结

尝试方式结果
方案 Amanifest.jsonapp-harmony.distribute.requestPermissions无效,构建系统不处理此字段
方案 Buni_modules harmony-permissions UTS 插件无效,权限不被合并,还导致 UTS 编译依赖缺失
方案 C构建后 node 脚本直接编辑 module.json5有效

五、核心教训

  1. manifest.jsonapp-harmony.distribute 支持字段非常有限(基本只有 icons),权限声明不是通过 manifest 配置的。

  2. 微信小程序能震动 ≠ 系统设置没问题。小程序运行在微信容器里,权限走的是微信的,和独立 App 完全不同。这个对比检验会误导排查方向。

  3. usage: 'touch' 理论上不需要权限,但实际可能需要。HarmonyOS 不同 SDK 版本的行为有差异,声明了权限更保险。

  4. 原生层的错误被吞没VibrateNative.etsstartVibration 的 Promise 错误只 console.error,JS 侧 success/fail 回调拿不到真实状态。排查时不能只看 JS 回调。

  5. 当构建系统不支持某个配置时,构建后脚本注入是最可靠的 fallbackdev-harmony.bat 本来就是自定义构建流程,加一步权限注入完全可控。


本文记录了 uni-app 鸿蒙 App 震动功能从失效到修复的完整排查过程,核心发现是鸿蒙权限配置无法通过 manifest.json 生效,需要构建后直接编辑 module.json5。希望对同样遇到鸿蒙权限问题的开发者有所帮助。

本文为开发实践记录,内容如有错误或不足,欢迎搜索微信公众号「卷王开发者」批评指正。共同进步,感谢阅读。

扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码