Flutter 3.47 鸿蒙三方库适配实战:从 0 到 1 处理 system_alert_window
Flutter 3.47 鸿蒙三方库适配实战:从 0 到 1 处理 system_alert_window
Android 的悬浮窗插件经常依赖跨应用显示窗口能力。迁移到鸿蒙时,不能只把插件目录改成 ohos,还要先确认权限模型、窗口类型和后台限制有没有直接等价 API。
本文以 system_alert_window 2.0.11 为例,记录 Flutter 3.47 鸿蒙适配过程:先找出原插件真实使用的 Channel,修正 Dart 与 ArkTS 的通道不一致问题,再让 OHOS 端准确返回悬浮窗权限不可用。文章不伪造“悬浮窗已经显示”,而是用真机验证正确的限制结果。
一、最终效果
{:width=“50%”}
图 1:API 26 真机启动适配后的 Demo。
{:width=“50%”}
图 2:真机检查后返回 false,页面显示当前平台不支持。
| 验证点 | 真机结果 |
|---|---|
| Flutter | 3.47.4-ohos-1.0.4 |
| HarmonyOS | 7.0.0.105,API 26 |
| HAP | signed HAP 构建通过 |
| Channel | Dart 与 ArkTS 统一为 in.jvapps.system_alert_window |
| 权限检查 | checkPermissions 返回 false |
| 适配结论 | 不伪造 Android 跨应用悬浮窗能力 |
二、先理解原插件的真实能力
原插件提供的主要接口包括:
SystemAlertWindow.checkPermissions();
SystemAlertWindow.requestPermissions();
SystemAlertWindow.showSystemWindow();
SystemAlertWindow.updateSystemWindow();
SystemAlertWindow.closeSystemWindow();
SystemAlertWindow.isBubbleMode();
这些方法在 Android 上围绕悬浮窗权限、WindowManager 和后台服务工作。它们不是普通 Flutter Overlay:
| 能力 | 普通 Flutter Overlay | Android 悬浮窗 | 鸿蒙端本次结论 |
|---|---|---|---|
| 覆盖当前 Flutter 页面 | 可以 | 可以 | 可以继续做页面内 UI |
| 覆盖其他应用 | 不可以 | 可以申请权限 | 没有直接等价实现 |
| 后台悬浮服务 | 不可以 | 依赖 Service | 需要单独 Ability 和权限方案 |
| Bubble 模式 | 不适用 | Android 专属 | 返回 false |
本次适配的边界是:保留原 Dart API、完成 OHOS 插件注册和权限查询,同时明确告诉业务层当前系统能力不可用。
三、准备 Flutter 3.47 和设备
本文实际环境:
| 工具 | 版本 |
|---|---|
| Flutter OH | 3.47.4-ohos-1.0.4 |
| Dart | 3.13.3 |
| DevEco Studio | 26.0.0 Release |
| HarmonyOS SDK | API 26 |
| 测试设备 | 127.0.0.1:5555,HarmonyOS 7.0.0.105 |
环境没有准备好时,先看 Flutter OH 环境搭建指南。
export PATH=/Users/von/Developer/flutter-oh-3.47.4/bin:$PATH
flutter --version
hdc list targets
四、拉取适配分支
本文使用的仓库信息:
- 仓库:AtomGit 仓库主页
- 适配分支:feat/ohos_system_alert_window_2.0.11
- 受测提交:0d9c771a272d0c19a77380e4599055f9f2aa913b
git clone https://atomgit.com/oh-flutter/system_alert_window.git
cd system_alert_window
git switch feat/ohos_system_alert_window_2.0.11
git log -1 --oneline
五、适配过程中的第一个问题:Channel 不一致
原 Dart 文件从常量中读取通道:
static const String CHANNEL = 'in.jvapps.system_alert_window';
static const MethodChannel _channel =
MethodChannel(Constants.CHANNEL);
原 OHOS 插件骨架监听的却是:
new MethodChannel(
binding.getBinaryMessenger(),
'system_alert_window',
);
两个字符串不同,Dart 调用就不会到达 ArkTS。适配时统一为:
this.channel = new MethodChannel(
binding.getBinaryMessenger(),
'in.jvapps.system_alert_window',
);
Channel 名称不是文件名,也不是 pub 包名,而是 Dart 和原生两边共同约定的通信地址。
六、第二个问题:Codec 也要对齐
原 Dart 使用 JSONMethodCodec,OHOS embedding 默认使用 StandardMessageCodec。两边 Codec 不一致时,参数可能无法解析,运行表现可能像插件没有响应。
本次把 Dart 端统一为默认 MethodChannel:
static const MethodChannel _channel =
MethodChannel(Constants.CHANNEL);
适配时需要同时核对:
| 项目 | 适配值 |
|---|---|
| Channel | in.jvapps.system_alert_window |
| Codec | Flutter 默认 StandardMessageCodec |
| 权限方法 | checkPermissions、requestPermissions |
| 生命周期 | onAttachedToEngine、onDetachedFromEngine |
七、声明 OHOS 插件平台
pubspec.yaml 增加:
flutter:
plugin:
platforms:
android:
package: in.jvapps.system_alert_window
pluginClass: SystemAlertWindowPlugin
ios:
package: in.jvapps.system_alert_window
pluginClass: SystemAlertWindowPlugin
ohos:
pluginClass: SystemAlertWindowPlugin
OHOS 入口:
import SystemAlertWindowPlugin from './src/main/ets/components/plugin/SystemAlertWindowPlugin';
export default SystemAlertWindowPlugin;
插件注册通道,并在引擎解绑时释放 handler:
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(
binding.getBinaryMessenger(),
'in.jvapps.system_alert_window',
);
this.channel.setMethodCallHandler(this);
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
this.channel?.setMethodCallHandler(null);
this.channel = null;
}
八、逐个映射权限和窗口方法
Dart 侧权限检查会发送:
_channel.invokeMethod(
'checkPermissions',
[Commons.getSystemWindowPrefMode(prefMode)],
);
OHOS 端处理:
case 'checkPermissions':
result.success(false);
return;
case 'requestPermissions':
result.success(false);
return;
case 'isBubbleMode':
result.success(false);
return;
关闭窗口是幂等操作,可以返回空结果:
case 'closeSystemWindow':
result.success(null);
return;
没有直接等价实现的跨应用悬浮窗方法不能返回 true。业务层需要知道当前平台没有完成这项能力。
九、创建最小 Demo
Demo 启动时自动查询权限:
void initState() {
super.initState();
_check();
}
Future<void> _check() async {
final allowed = await SystemAlertWindow.checkPermissions(
prefMode: SystemWindowPrefMode.OVERLAY,
);
if (!mounted) return;
setState(() {
_status = allowed == true ? '允许' : '当前平台不支持';
_detail = 'checkPermissions 返回:$allowed';
});
}
页面还提供重新检查按钮。真机显示:
当前平台不支持
checkPermissions 返回:false
这个 Demo 验证的是插件适配结果,不会弹出 Android 权限申请流程。
十、构建、签名和安装
flutter pub get
flutter analyze
cd example
flutter test
flutter build hap --debug --no-codesign
配置 DevEco 调试签名后:
flutter build hap --debug
hdc list targets
hdc install -r build/ohos/hap/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.example.flutter_oh_demo
本文使用 signed HAP 在 API 26 真机启动和检查权限。签名文件和密码没有提交。
十一、真机验证
真机启动后,页面自动读取 checkPermissions,显示“当前平台不支持”。点击重新检查后仍然返回 false。
完整链路如下:
- Dart 调用原插件 API。
- MethodChannel 使用上游约定的 Channel。
- StandardMessageCodec 传递参数。
- ArkTS 插件被加载。
- OHOS 端返回准确的平台能力结果。
本次没有把 Android 跨应用悬浮窗伪装成鸿蒙已支持。真正的跨应用窗口还需要单独研究 HarmonyOS UIExtension、WindowStage、权限和后台生命周期。
十二、常见问题
Q1:为什么不直接返回 true
当前没有完成跨应用悬浮窗能力。返回 true 会让业务以为窗口已经可以显示,实际却看不到覆盖窗口。
Q2:为什么 Channel 要用 in.jvapps.system_alert_window
这是原 Dart 代码的真实常量。原生端必须匹配它,不能根据仓库名自行改成 system_alert_window。
Q3:为什么要去掉 JSONMethodCodec
OHOS embedding 端默认使用标准消息编解码。两边 Codec 不一致时,参数可能无法解析,表现可能像插件没有响应。
Q4:页面内 Flutter Overlay 能不能继续使用
页面内 Overlay 属于 Flutter 自己的渲染范围,可以单独实现。本文验证的是跨应用悬浮窗能力,不能把两者混在一起。
Q5:返回 false 算适配完成吗
本文完成的是 OHOS 平台注册、通道对齐和准确能力返回。跨应用悬浮窗原生能力仍需另一个独立实现任务,不能用 false 冒充完整悬浮窗。
十三、复现命令
git clone https://atomgit.com/oh-flutter/system_alert_window.git
cd system_alert_window
git switch feat/ohos_system_alert_window_2.0.11
export PATH=/Users/von/Developer/flutter-oh-3.47.4/bin:$PATH
flutter pub get
flutter analyze
cd example
flutter test
flutter build hap --debug --no-codesign
十四、总结
这次适配从 Dart 真实 Channel、Codec、方法名和权限语义四个方面排查。Android 跨应用悬浮窗在鸿蒙端没有直接等价实现时,最可靠的做法是保留 API、统一通道、返回准确的 false,并让业务层可以明确降级。
十五、参考资料与仓库地址
本文适配仓库
上游和包信息
Flutter 和鸿蒙资料
- Flutter 官方插件开发文档
- Flutter MethodChannel 文档
- Flutter PlatformInterface 文档
- Flutter OH 环境搭建指南
- HarmonyOS 开发者官网
- HarmonyOS ArkTS 文档
- HarmonyOS UIExtension 文档
- HarmonyOS Window 文档
- HarmonyOS 应用签名和调试文档
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐



所有评论(0)