Flutter 鸿蒙插件适配实战:用 device_screen_brightness 2.0.0 控制并监听屏幕亮度

适配仓库: https://atomgit.com/oh-flutter/device_screen_brightness

适配分支: feat/ohos_device_screen_brightness_2.0.0

受测提交: 3a842e4982e788a494c5034aac932d1c2b779946

一、最终效果与适配目标

阅读器、视频播放器和夜间工具经常需要临时调节当前页面亮度。device_screen_brightness 2.0.0 已把读取、写入、增减、变化监听和能力查询整理成统一 Dart API,但上游没有 OHOS 实现。本次适配保持这些公共接口不变,在 OHOS 侧补上"应用窗口亮度"和"系统亮度"两种模式。

我优先验证不需要特殊权限的 BrightnessMode.app:进入页面时读取当前亮度,拖动滑块后回读实际值,监听流同步更新,离开页面或插件解绑时恢复原窗口值。系统模式也完成了读取和拒绝权限路径,但普通应用没有 MANAGE_SETTINGS 授权,所以没有把"系统亮度写入成功"写成真机结论。

图 1:CHZ-AL00 / HarmonyOS 7.0.0.105 上读取到应用窗口继承的初始亮度,系统自动亮度保持开启。

图 2:在应用模式拖动滑块后,页面数值、窗口回读和事件记录同步变化。

图 3:后一轮独立测试中将窗口恢复为 -1,即重新跟随系统亮度;该图的 19% 与图 1、图 2 不是同一次连续回环。

验证点 实测结果 证据
应用亮度读取与写入 0 到 100 的整数值可读取,写入后独立窗口属性回读一致 图 1、图 2、图 8
亮度变化流 订阅时先发当前值,后续变化去重投递 图 2、图 8
页面退出与插件解绑 原窗口亮度 -1 得到恢复 图 3、图 8
系统写入权限 未授权时明确返回 permission_denied 图 8
自动化与构建 44 项功能测试、静态分析和 HAP 构建通过 图 6、图 7

二、成果速览

项目 内容
上游基线 TAG v2.0.0,提交 d0aa9305d73cff8f9e0f7b65f6586c3380b7af94,MIT
适配分支 feat/ohos_device_screen_brightness_2.0.0
适配提交 3a842e4982e788a494c5034aac932d1c2b779946
新增 OHOS 能力 应用/系统亮度读取、写入、增减、事件、能力与权限查询、窗口恢复
保持不变的接口 DeviceScreenBrightnessBrightnessMode、原 MethodChannel/EventChannel
自动化验证 24 项 Dart、2 项 Widget、18 项 ArkTS,共 44 项
真机结论 应用模式 14 项检查通过;系统授权写入、外部系统变化和其他机型未验证

2026 年 9 月 11 日适配前,我重新核对了发布版本、上游 HEAD、三方库清单以及目标组织同名仓库,没有发现可直接使用的 OHOS 实现。这个结论只对应当时核查范围,不把它扩大成全网结论。

三、实测环境

组件 实测版本
Flutter OH 3.41.10-ohos-1.0.1
Dart 3.11.5
DevEco Studio 26.0.0 Release
HarmonyOS SDK API 26;示例 compatibleSdkVersion 为 18
真机 CHZ-AL00,HarmonyOS 7.0.0.105
插件 device_screen_brightness 2.0.0

环境搭建直接参考 Flutter OH 环境搭建指南。截至 2026 年 9 月 12 日,版本号最大的 Flutter OH 标签 3.44.9+ohos-0.0.1-canary1 仍是预览版;本文使用完成构建和真机回归的正式稳定版 3.41.10-ohos-1.0.1,不把预览版本写成受测环境。

四、同步上游并建立适配分支

上游 2.0.0 已完成平台通道化,适合作为稳定基线。我保留上游 Git 历史与 MIT 许可证,将代码同步到 AtomGit 后,从 v2.0.0 创建统一命名分支:

shell 复制代码
git clone https://atomgit.com/oh-flutter/device_screen_brightness.git
cd device_screen_brightness
git switch -c feat/ohos_device_screen_brightness_2.0.0 v2.0.0
flutter create --template=plugin --platforms=ohos --no-pub .

模板只负责生成 ohos/example/ohos/ 骨架。随后必须把插件类、通道名称和示例代码改回本库真实契约,不能保留模板的 getPlatformVersion

图 4:AtomGit origin、适配分支、完整 HEAD 和干净工作区的实际核验。

五、先固定原有 API 契约

公共 API 使用 0 到 100 的整数刻度,调用者不需要理解 OHOS 窗口值的 0 到 1 或系统设置值的 0 到 255:

dart 复制代码
final int current = await DeviceScreenBrightness.getBrightness(
  mode: BrightnessMode.app,
);
final int applied = await DeviceScreenBrightness.setBrightness(
  65,
  mode: BrightnessMode.app,
);
final Stream<int> changes = DeviceScreenBrightness.streamBrightness(
  mode: BrightnessMode.app,
);

方法通道保持 dev.arcas.device_screen_brightness/methods,事件通道保持 dev.arcas.device_screen_brightness/events。OHOS 端只增加平台实现,不改 Android、iOS、桌面端原生源码。Dart 分发额外识别 Platform.operatingSystem == 'ohos',否则 app 模式事件会被错误当作 system 过滤。

六、OHOS 端的窗口与系统两条路径

pubspec.yaml 注册 DeviceScreenBrightnessPlugin。应用模式通过当前 UIAbility 的主窗口读写,系统模式通过 Settings 读取 0 到 255 的系统值:

typescript 复制代码
if (mode === 'app') {
  const raw = this.readWindow(session).getWindowProperties().brightness;
  if (raw >= 0 && raw <= 1) return Math.round(raw * 100);
}

const raw = settings.getValueSync(
  session.ability.context,
  settings.display.SCREEN_BRIGHTNESS_STATUS,
  '',
);
return Math.round(Number(raw) / 255 * 100);

窗口属性为 -1 时表示继承系统值,因此读取应用亮度时会回退到系统设置。第一次写应用亮度前,插件保存窗口 ID 和原值;解绑时只有当前窗口值仍等于插件最后写入值才恢复,避免覆盖宿主其他组件后来设置的新亮度。原生浮点回读可能是 0.699999988079071,比较时必须容忍 float32 精度,而不能只写 value === 0.7

系统模式写入前检查 ohos.permission.MANAGE_SETTINGS。该权限不能由普通运行时弹窗授予,requestPermission() 在无授权时会抛出稳定的 PermissionDeniedException,而不是假装请求成功。应用窗口模式不需要这个权限,也不会主动关闭系统自动亮度。

事件层在 Dart 存在订阅者时每 250 ms 读取两种模式并去重;取消最后一个订阅后停止轮询。写操作放进串行队列,避免连续加减与恢复操作交叉。

图 5:窗口/系统模式分发、单位换算、权限检查和写后回读的受测实现。

七、交付文件与自动化验证

适配分支新增 OHOS HAR、独立示例、双语 OHOS 文档、Dart/Widget 测试、生产 ArkTS mock 测试与真机探测入口。上游源码、许可证和其他平台实现保持不变;签名材料、local.properties、依赖缓存与 HAP 不提交。

shell 复制代码
flutter pub get
flutter analyze
flutter test
node --test ohos/test/device_screen_brightness_plugin.test.cjs
cd example
flutter test
flutter build hap --debug --no-codesign

24 项 Dart、2 项 Widget 和 18 项 ArkTS 测试全部通过。覆盖范围包括参数边界、单位映射、写后回读、权限拒绝、事件去重、取消与重订阅、并发顺序、写入中解绑、窗口切换及原值恢复。

图 6:静态检查和 44 项自动化功能测试的真实结果汇总。

图 7:无签名 HAP 的实际大小、SHA-256 与受测代码提交。

八、固定提交接入并做真机回环

当前没有 OHOS 稳定 TAG,因此 Demo 用完整 SHA 锁定:

yaml 复制代码
dependencies:
  device_screen_brightness:
    git:
      url: https://atomgit.com/oh-flutter/device_screen_brightness.git
      ref: 3a842e4982e788a494c5034aac932d1c2b779946

执行 flutter pub get 后,应在 pubspec.lock 中确认 resolved-ref 与上面 SHA 一致。最终真机探测共 14 项通过:能力查询、应用亮度读取、写入、增减、事件、非法值、系统权限拒绝、独立窗口回读,以及从 Engine 移除插件后的原值恢复。最终窗口回到 -1,系统自动亮度仍为 1。

图 8:真机检查成功项与未覆盖边界同时保留,没有把权限拒绝包装成成功写入。

需要特别说明,图 1、图 2 记录的是一轮 45% -> 65% 操作;图 3 是下一天系统环境为 19% 时拍摄的恢复页。两组图都是真实结果,但不能拼成一次连续的 45 -> 65 -> 19 回环。

应用内补拍:连续事件与真实回读

图 9:再次把应用窗口调到 45% 后,页面同时展示窗口回读、系统自动亮度和连续亮度事件。

九、FAQ

Q1:为什么应用模式初次读取到系统亮度

  • 现象: 窗口属性为 -1,页面仍能显示一个 0 到 100 的亮度值。
  • 原因: -1 表示窗口没有独立覆盖,实际亮度继承系统设置。
  • 解决方法: 应用模式读取遇到 -1 时回退读取系统亮度;恢复时写回 -1
  • 验证结果: 真机退出页面后窗口回读为 -1,页面重新跟随系统亮度。

Q2:系统模式为什么一直报 permission_denied

  • 现象: setBrightness(..., mode: BrightnessMode.system) 被拒绝。
  • 原因: OHOS 全局亮度写入要求 MANAGE_SETTINGS,普通应用不能通过运行时对话框获得。
  • 解决方法: 普通业务优先使用 BrightnessMode.app;只有具备相应系统授权的宿主才启用系统模式。
  • 验证结果: 自动化和真机均确认拒绝错误稳定返回,没有误改系统自动亮度。

Q3:为什么恢复比较不能严格等于 0.7

  • 现象: ArkTS 写入 0.7,真实窗口回读 0.699999988079071
  • 原因: 原生窗口属性使用浮点表示,存在正常精度差。
  • 解决方法: 用小容差判断当前值是否仍是插件写入值,再决定是否恢复。
  • 验证结果: 修复后 18 项原生回归和最终 14 项真机检查通过。

十、总结

这次适配保留了 device_screen_brightness 的完整 Dart API,在 OHOS 端补上应用/系统模式、事件监听、能力与权限查询,并把窗口恢复作为生命周期的一部分处理。44 项自动化、HAP 构建和 API 26 真机应用模式回环均已通过。

当前证据不包含系统授权后的全局写入、外部设置页变化、长期轮询和其他设备。业务接入时应默认显式选择 BrightnessMode.app,并继续锁定受测提交,等正式 OHOS TAG 发布后再升级。

十一、参考链接

欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter

相关推荐
ChinaDragon1 小时前
HarmonyOS:应用横竖屏切换
harmonyos
颜颜yan_2 小时前
ESP-IDF 鸿蒙 PC 适配全记录:打通 Python、构建工具链与 ESP32-P4 固件生成
python·华为·harmonyos
梦想不只是梦与想4 小时前
鸿蒙 邀请测试:AppGallery邀请测试流程
harmonyos·appgallery 邀请测试·邀请测试
贾伟康7 小时前
【口算王|02】HarmonyOS ArkTS 答题提交实战:防止重复提交并推进下一题
harmonyos·arkts·状态管理·arkui·幂等设计
承渊政道9 小时前
Python IDLE鸿蒙PC适配全记录:从Tkinter桌面程序到ArkUI原生开发闭环
开发语言·python·harmonyos·鸿蒙系统·桌面程序
风早爽太9 小时前
Flutter 开发笔记:share_plus 分享插件
笔记·flutter
万物智能信息科技9 小时前
电容触摸 FT5406,另一颗芯片、同一条总线—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
人工智能·华为·开源·harmonyos·鸿蒙
ChinaDragonDreamer10 小时前
HarmonyOS:应用程序包管理模块(获取当前应用信息)
harmonyos·鸿蒙
●VON10 小时前
Flutter 鸿蒙插件适配实战:用 boot_time_plugin 1.0.0 读取启动时间与运行时长
flutter·华为·harmonyos