Flutter 鸿蒙插件适配实战:用 is_lock_screen 2.0.0 判断真实锁屏状态

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

适配分支: feat/ohos_is_lock_screen_2.0.0

一、最终效果、需求与边界

音视频通话、敏感信息刷新、前后台恢复等业务,有时需要区分"应用不在前台"和"设备真的进入锁屏"。屏幕熄灭、返回桌面、应用暂停都不能直接等同于锁屏。is_lock_screen 2.0.0 已提供顶层 Future<bool?> isLockScreen(),但原仓库没有 OHOS 实现。

本次适配直接调用系统锁屏查询,不用亮度、电源状态或 Flutter 生命周期猜测。true 表示已锁屏,false 表示未锁屏,null 表示读取失败后的未知状态。特别是最后一点,业务如果把 null 当成 false,会在系统 API 不可用时误判为"已解锁"。

图 1:真机联合宿主中的锁屏状态读取页面。

验证点 实测结果 证据
解锁状态 返回 false 图 1、图 6
锁屏状态 同一 PID 的后续采样返回 true 图 6
解锁恢复 再次返回 false 图 6
自动化与构建 7 项 Dart/Widget 测试、静态分析和 HAP 构建通过 图 4、图 5
验证限制 60 秒单窗口自动用例未观察到完整回环,系统 API 已弃用 图 6、实现说明

成果速览

项目 内容
上游基线 2.0.0 对应提交 c88c27cc48474cc9c1159334a9bc40aff9ed73a8,MIT
适配分支 feat/ohos_is_lock_screen_2.0.0
适配 TAG 尚未发布
真机受测提交 a3574eae572c27aa4fdf97ca8d55b089a7696525
当前分支 HEAD 755817832652366875c85a3e1271c37a9a1bd3a6,后续仅增加设备记录
返回语义 true 已锁屏、false 未锁屏、null 读取失败
真机结论 同 PID 跨采样窗口完成 false -> true -> false,不等于连续自动用例通过

二、实测环境

项目 实际值
Flutter OH 3.41.10-ohos-1.0.1
Dart 3.11.5
DevEco Studio 26.0.0 Release
HarmonyOS SDK API 26,示例兼容 API 18
设备 CHZ-AL00,HarmonyOS 7.0.0.105
插件 is_lock_screen 2.0.0

工具安装不再重复,参考 Flutter OH 环境搭建指南。截至 2026 年 9 月 12 日,版本号最大的标签是预览版 3.44.9+ohos-0.0.1-canary1,最新正式稳定标签仍是本文实测的 3.41.10-ohos-1.0.1

三、仓库同步和分支

适配基线为上游提交 c88c27cc48474cc9c1159334a9bc40aff9ed73a8,对应 2.0.0,保留 MIT 许可证。适配前核对待适配、适配中、已适配清单及组织仓库,当日未发现该包已有 OHOS 交付。

shell 复制代码
git clone https://atomgit.com/oh-flutter/is_lock_screen.git
cd is_lock_screen
git switch feat/ohos_is_lock_screen_2.0.0
git branch --show-current

从原基线建立分支并补平台骨架:

shell 复制代码
git switch -c feat/ohos_is_lock_screen_2.0.0 c88c27cc48474cc9c1159334a9bc40aff9ed73a8
flutter create --template=plugin --platforms=ohos --no-pub .

图 2 汇总了实际 AtomGit origin、适配分支和 HEAD,可核对仓库来源与当前分支状态。

图 2:AtomGit origin、统一适配分支和 HEAD。

四、保留原来的可空 API

原库 Dart 入口很短:

dart 复制代码
final _channel = MethodChannel('is_lock_screen');

Future<bool?> isLockScreen() async {
  try {
    return await _channel.invokeMethod('isLockScreen') as bool?;
  } on PlatformException {
    return null;
  }
}

OHOS 端只需注册同名通道和方法,但错误策略必须与上层配合:原生失败抛出平台异常,Dart 再转成 null。因此示例页面用了三态显示,而不是简单写 locked ?? false

五、调用鸿蒙锁屏 API

pubspec.yaml 注册 IsLockScreenPlugin,ArkTS 通过 @kit.BasicServicesKit 调用 screenLock.isScreenLocked()

typescript 复制代码
if (call.method !== 'isLockScreen') {
  result.notImplemented();
  return;
}

try {
  result.success(await screenLock.isScreenLocked());
} catch (error) {
  result.error(
    'LOCK_STATE_UNAVAILABLE',
    'Failed to read the system screen lock state.',
    null,
  );
}

这个接口从 API 7 提供,但自 API 9 起已弃用;公开替代接口面向系统应用。当前 SDK 仍能编译,API 26 真机也返回了正确结果,但这不能外推为所有未来系统都兼容。文章必须把弃用状态放在实现旁边,而不是藏在文末。

插件不执行锁屏或解锁,也不申请额外权限。未知方法返回 notImplemented,系统失败不回退到屏幕亮灭状态。

实际业务还要决定在哪个时机读取。支付页可以在回到前台时重新确认,通话页可以把锁屏状态作为一个信号,但不应靠高频轮询控制核心安全策略。系统鉴权、页面脱敏和服务端会话仍应独立存在。

图 3:screenLock.isScreenLocked() 调用与失败透传路径。

六、交付文件与示例

本分支保留原 API、Android/iOS 实现、MIT LICENSE 和 Git 历史;补充 OHOS 注册、HAR、example/ohos/、双语 OpenHarmony 文档、Dart 与 widget 测试、设备集成入口。上游示例原先不支持空安全的依赖也调整为与 Dart 3 工具链兼容。

示例在初始化、按钮刷新和生命周期恢复时读取状态,并明确显示"未知"。这比持续高频轮询更适合普通业务;锁屏后后台执行可能暂停 Dart timer,本就不能保证连续采样。

七、自动化验证与构建

shell 复制代码
flutter pub get
flutter analyze
flutter test
cd example
flutter test
flutter build hap --debug --no-codesign

插件 4 项测试和示例 3 项 widget 测试通过,共 7 项;静态分析无问题,无签名 HAP 构建成功。它们覆盖通道契约、bool/null、异常降级、页面刷新和生命周期更新,但 mock 与编译都不能证明系统锁屏状态真实可读。

隔离宿主通过 AtomGit 固定到 a3574eae572c27aa4fdf97ca8d55b089a7696525 并完成签名构建和真机调用。后续提交只增加设备记录。

图 4:Flutter 复跑与 7 项 Dart/ArkTS 用例统计。

八、真机如何验证锁屏回环

yaml 复制代码
dependencies:
  is_lock_screen:
    git:
      url: https://atomgit.com/oh-flutter/is_lock_screen.git
      ref: a3574eae572c27aa4fdf97ca8d55b089a7696525

执行 flutter pub get 后,应确认 pubspec.lockresolved-ref 与上述真机受测 SHA 一致。后续设备文档提交不会改变受测代码事实。

同一宿主进程 PID 53703 留下了三条真实样本:解锁时为 false;按电源键并独立确认锁屏 UI 后,读取为 true;用户解锁返回应用后,再读为 false。带时刻的序列是 11:44:13.378 false -> 11:44:14.712 true -> 14:02:30.899 false

这完成了同进程、跨采样窗口的 false -> true -> false 回环,但单个 60 秒自动采样用例没有观测到完整回环,状态仍是 incomplete。原因是锁屏期间应用计时器和日志投递可能暂停,不能把跨窗口人工验收写成自动用例 PASS。

"同一 PID"在这里很关键,它排除了卸载、重装或新进程默认状态对结果的干扰;而"跨采样窗口"又说明这不是一个连续自动脚本。两个限定词都应保留在图注和结论中。

图 5:HAP 产物摘要与真机宿主使用的 resolved-ref。

图 6:同 PID 跨采样窗口的 false -> true -> false,以及未伪装成功的 incomplete 自动用例。

九、提交与远端核对

shell 复制代码
git status --short
git add pubspec.yaml ohos example test README.OpenHarmony.md README.OpenHarmony_CN.md
git commit -m "feat: add OHOS support for is_lock_screen"
git push -u origin feat/ohos_is_lock_screen_2.0.0

仓库已公开,默认分支为适配分支。2026 年 9 月 12 日匿名读取的 HEAD 为 755817832652366875c85a3e1271c37a9a1bd3a6,工作区没有签名、凭据和构建产物。

十、FAQ

Q1:返回 null 是否表示没有锁屏

  • 现象: isLockScreen() 返回 null
  • 原因: 原 Dart API 把平台读取异常转换成未知状态。
  • 解决方法: UI 和业务逻辑单独处理 unknown,不能用 ?? false 掩盖错误。
  • 验证结果: 单元测试覆盖异常到 null 的路径。

Q2:熄屏后为什么没立刻记录 true

  • 现象: 锁屏期间轮询日志暂停。
  • 原因: 应用进入后台后 Dart timer 可能被系统挂起;熄屏本身也不必然等于锁屏完成。
  • 解决方法: 在解锁回到前台时重新读取,并结合独立锁屏 UI 确认。
  • 验证结果: 同一 PID 跨窗口观测到完整三态序列。

Q3:API 已弃用还能用于生产吗

  • 现象: 当前 SDK 可编译,文档却标记 deprecated。
  • 原因: 公共替代能力目前只面向系统应用。
  • 解决方法: 对目标机型和系统版本建立兼容矩阵,失败时走 unknown 降级,并持续关注 SDK 变化。
  • 验证结果: 目前仅确认 API 26 指定真机,不宣称普遍兼容。

十一、总结

is_lock_screen 的 OHOS 实现直接读取真实锁屏状态,保留了 bool? 的失败语义,没有用屏幕或生命周期猜测。7 项自动化、HAP 构建和指定真机上的 false -> true -> false 都有记录;同时,单窗口自动用例未完整通过、底层 API 已弃用,这两项限制也必须和成功结果一起发布。

十二、参考链接

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

相关推荐
Sunny_G3 小时前
鸿蒙 Markdown 编辑器表格所见即所得:七个版本的渲染重构(CodeMirror Decoration 实战)
ai编程·harmonyos
linnux领域4 小时前
eNSP 交换机与电脑不在一个网段?用一台 Windows 双网卡做路由,把实验环境彻底打通
windows·华为·电脑·ensp·静态路由·网络实验·ensp模拟器
●VON4 小时前
Flutter 鸿蒙插件适配实战:用 flutter_timezone_observer 1.2.0 监听系统时区变化
flutter·华为·harmonyos
云运维笔记4 小时前
华为VRP系统文件管理全攻略
前端·华为
●VON4 小时前
Flutter 鸿蒙 app_install_date 0.1.5 使用实战:读取应用安装时间
flutter·华为·harmonyos
Dream-Y.ocean4 小时前
鸿蒙平台 Apache Tomcat 管理控制台适配实战:基于 Electron 壳方案的真实 HTTP 服务器实现
tomcat·apache·harmonyos
●VON6 小时前
Flutter 鸿蒙插件适配实战:flutter_screenshot_detect 0.1.7 截图事件监听
flutter·华为·harmonyos·鸿蒙
GLAB-Mary8 小时前
90%的网络工程师,根本没必要考HCIE!
网络·华为·华为认证·hcie·hcia·hcip