Flutter 鸿蒙 is_lock_screen 2.0.0 使用实战:区分锁屏、解锁与未知状态
本文用
is_lock_screen 2.0.0在 Flutter 鸿蒙页面读取设备锁屏状态,并结合应用生命周期处理
true、false、null三种结果。它适合通话、敏感页面恢复和状态刷新辅助判断,但不能替代系统身份认证。三方库仓库: https://atomgit.com/oh-flutter/is_lock_screen
本文锁定版本:
a3574eae572c27aa4fdf97ca8d55b089a7696525完整 Demo: is_lock_screen/example(受测提交)
一、最终真机效果

图 1:CHZ-AL00 / HarmonyOS 7.0.0.105 上展示锁屏查询结果和 Flutter 生命周期状态。


同一应用进程留下了 false -> true -> false 三个真实样本:设备解锁时为 false,进入锁屏后为 true,用户解锁并返回应用后再次为 false。由于锁屏期间 Dart timer 和日志可能暂停,这组结果来自同 PID 的跨采样窗口,不应写成单个连续自动用例已经通过。
| 返回值 | 业务含义 | 推荐处理 |
|---|---|---|
true | 系统报告设备已锁屏 | 暂停敏感内容、等待恢复 |
false | 系统报告设备未锁屏 | 再结合应用前后台状态处理 |
null | 平台读取失败或状态未知 | 保守降级并记录错误,不能当成 false |
二、适用范围与重要限制
应用进入后台不一定是锁屏,可能只是用户回到桌面或切换了应用;屏幕熄灭也不应直接当作系统已经完成锁定。这个库直接查询系统锁屏状态,比从亮度或 Flutter 生命周期猜测可靠,但它只提供一个时刻的快照。
OHOS 适配底层使用的 screenLock.isScreenLocked() 从 API 9 起已标记废弃,公开替代能力目前面向系统应用。本文在 API 26 指定真机上验证可用,不代表未来系统或所有设备都保证兼容。生产项目必须保留 null 分支,并建立自己的设备和系统版本矩阵。
涉及支付、口令或隐私数据时,锁屏状态只能作为界面脱敏信号。真正的身份确认仍应使用系统认证能力,服务端会话也不能只依赖这个布尔值。
三、环境与依赖
| 组件 | 实测版本 |
|---|---|
| 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 / 上述受测提交 |
预览标签 3.44.9+ohos-0.0.1-canary1 未用于本文回归。适配尚未发布稳定 TAG,因此锁定完整 SHA:
dependencies:
is_lock_screen:
git:
url: https://atomgit.com/oh-flutter/is_lock_screen.git
ref: a3574eae572c27aa4fdf97ca8d55b089a7696525
flutter pub get
确认 pubspec.lock 的 resolved-ref 后再构建。本库只读取锁屏状态,不执行锁定或解锁,也不需要新增鸿蒙权限。

图 2:AtomGit 仓库、适配分支和当前提交。
四、核心 API 与三态判断
import 'package:is_lock_screen/is_lock_screen.dart';
final bool? locked = await isLockScreen();
switch (locked) {
case true:
// 系统明确报告已锁屏
break;
case false:
// 系统明确报告未锁屏
break;
case null:
// 读取失败,保持未知状态
break;
}
不要写成 final unlocked = !(locked ?? false)。这种表达会把读取错误当作已解锁,恰好在需要保守处理的场景中放宽保护。
五、跟随生命周期重新读取
import 'package:flutter/material.dart';
import 'package:is_lock_screen/is_lock_screen.dart';
class LockStatePage extends StatefulWidget {
const LockStatePage({super.key});
State<LockStatePage> createState() => _LockStatePageState();
}
class _LockStatePageState extends State<LockStatePage>
with WidgetsBindingObserver {
bool? _locked;
bool _loading = false;
String _lifecycle = 'resumed';
int _requestId = 0;
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_refresh();
}
Future<void> _refresh() async {
final requestId = ++_requestId;
setState(() => _loading = true);
final result = await isLockScreen();
if (!mounted || requestId != _requestId) return;
setState(() {
_locked = result;
_loading = false;
});
}
void didChangeAppLifecycleState(AppLifecycleState state) {
if (!mounted) return;
setState(() => _lifecycle = state.name);
if (state == AppLifecycleState.resumed ||
state == AppLifecycleState.paused ||
state == AppLifecycleState.inactive) {
_refresh();
}
}
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
Widget build(BuildContext context) {
final label = switch (_locked) {
true => '已锁屏',
false => '未锁屏',
null => '状态未知',
};
return Scaffold(
appBar: AppBar(
title: const Text('锁屏状态'),
actions: [
IconButton(
tooltip: '刷新',
onPressed: _loading ? null : _refresh,
icon: const Icon(Icons.refresh),
),
],
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(_locked == true ? Icons.lock : Icons.lock_open, size: 48),
const SizedBox(height: 12),
Text(_loading ? '读取中' : label),
Text('应用状态:$_lifecycle'),
],
),
),
);
}
}
请求编号用来丢弃晚到结果。锁屏期间应用可能被冻结,所以不要依靠 Timer.periodic 保证持续采样;最有价值的刷新时机通常是 resumed,即用户返回应用时。

图 3:OHOS 端直接调用系统锁屏查询,并把失败交给 Dart 转为 null。
六、测试、构建与真机验收
flutter analyze
flutter test
cd example
flutter test
flutter build hap --debug --no-codesign

图 4:7 项 Dart/Widget 测试与静态检查结果。

图 5:HAP 构建结果及真机宿主锁定的 SHA。

图 6:同一 PID 跨采样窗口的 false -> true -> false,同时保留单窗口自动用例 incomplete 的事实。
正确的人工步骤是:先在解锁状态读取 false;按电源键并确认真实锁屏界面后等待采样;再由用户解锁并回到应用读取 false。不要用测试命令绕过锁屏认证,也不要仅凭应用进入 paused 就断言已锁屏。
七、常见问题
Q1:返回 null 是不是表示没锁屏
不是。null 表示读取失败或未知。敏感页面应保持遮挡、提示重试或要求重新认证。
Q2:按下电源键后为什么没有立即打印 true
应用进入后台后 Dart 任务可能暂停,且熄屏与锁定完成不是同一时刻。解锁回前台后再读取,必要时结合原生日志核对。
Q3:底层 API 已废弃还能上线吗
只能在你的目标系统矩阵验证后谨慎使用,并实现未知状态降级。本文只确认 HarmonyOS 7.0.0.105 / API 26 这一台设备。
八、总结
is_lock_screen 可以帮助 Flutter 鸿蒙应用区分真实锁屏与普通前后台切换。接入时最重要的是保留 bool? 三态、在生命周期恢复时重新读取,并把底层废弃 API 的兼容风险写进产品策略。本文已完成指定真机跨采样回环,但没有把它夸大成连续自动化或全系统兼容结论。
九、参考链接
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐

所有评论(0)