适配仓库: 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.lock 的 resolved-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