Flutter三方库适配OpenHarmony【flutter_web_auth】— onMethodCall 方法分发与参数提取
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net和。authenticate 的参数提取和错误处理逻辑更复杂——因为它涉及到打开浏览器这个"跨进程"操作。两个方法:authenticate(异步)和 cleanUpDanglingCalls(同步)参数提取:call.argument() + as 类型断言preferEphemeral
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
flutter_web_auth 的 onMethodCall 只需要处理两个方法:authenticate 和 cleanUpDanglingCalls。authenticate 的参数提取和错误处理逻辑更复杂——因为它涉及到打开浏览器这个"跨进程"操作。
一、onMethodCall 完整实现
1.1 源码
onMethodCall(call: MethodCall, result: MethodResult): void {
console.info(TAG, `onMethodCall: ${call.method}`);
if (call.method == "authenticate") {
const url = call.argument('url') as string;
const callbackUrlScheme = call.argument('callbackUrlScheme') as string;
console.info(TAG, `authenticate called with url=${url}, scheme=${callbackUrlScheme}`);
this.authenticate(url, callbackUrlScheme, result);
} else if (call.method == "cleanUpDanglingCalls") {
this.cleanUpDanglingCalls(result);
} else {
result.notImplemented();
}
}
1.2 方法分发表
| 方法名 | 参数 | 处理函数 | 返回值 |
|---|---|---|---|
| authenticate | url, callbackUrlScheme, preferEphemeral | this.authenticate() | 异步(等待回调) |
| cleanUpDanglingCalls | 无 | this.cleanUpDanglingCalls() | null |
| 其他 | - | result.notImplemented() | 错误 |
1.3 与 secure_application 的对比
| 维度 | flutter_web_auth | secure_application |
|---|---|---|
| 方法数量 | 2个 | 5个 |
| 分发方式 | if-else | switch-case |
| 默认处理 | notImplemented() | success(true) |
| 异步方法 | ✅ authenticate | ❌ 全部同步 |
💡 flutter_web_auth 用 if-else 而不是 switch-case,因为只有两个方法,if-else 更简洁。secure_application 有五个方法,switch-case 更清晰。
二、authenticate 方法的参数提取
2.1 Dart 层传递的参数
// Dart 层
return await _channel.invokeMethod('authenticate', <String, dynamic>{
'url': url,
'callbackUrlScheme': callbackUrlScheme,
'preferEphemeral': preferEphemeral ?? false,
});
2.2 原生层提取参数
const url = call.argument('url') as string;
const callbackUrlScheme = call.argument('callbackUrlScheme') as string;
2.3 参数对照表
| Dart 参数 | 类型 | 原生提取 | 是否使用 |
|---|---|---|---|
| url | String | call.argument('url') as string |
✅ |
| callbackUrlScheme | String | call.argument('callbackUrlScheme') as string |
✅ |
| preferEphemeral | bool | 未提取 | ❌ 忽略 |
2.4 preferEphemeral 被忽略
// 当前实现中没有提取 preferEphemeral
// const preferEphemeral = call.argument('preferEphemeral') as boolean;
OpenHarmony 的 openLink API 不支持隐私浏览模式,所以 preferEphemeral 参数被静默忽略了。
📌 这是一个有意的设计决策,不是遗漏。如果未来 OpenHarmony 支持了隐私浏览,可以在这里提取并使用这个参数。
三、call.argument() 类型转换
3.1 类型安全
const url = call.argument('url') as string;
call.argument() 返回的是 ESObject 类型(类似 any),需要用 as 进行类型断言。
3.2 可能的类型问题
| 场景 | Dart 传递 | 原生接收 | 结果 |
|---|---|---|---|
| 正常 | 'url': 'https://...' |
as string |
✅ |
| null 值 | 'url': null |
as string |
null(不会崩溃) |
| 缺少参数 | 没有 ‘url’ 键 | as string |
null |
| 类型错误 | 'url': 123 |
as string |
“123”(自动转换) |
3.3 空值防御
// 当前实现没有做空值检查
const url = call.argument('url') as string;
// 如果 url 为 null,openLink(null) 会失败
// 更安全的写法
const url = call.argument('url') as string;
if (!url) {
result.error("INVALID_ARGS", "url is required", null);
return;
}
当前实现依赖 Dart 层的参数校验(required String url),所以原生层没有做额外的空值检查。这是合理的——Dart 的 required 关键字保证了参数不会为 null。
四、cleanUpDanglingCalls 的触发与清理
4.1 实现
private cleanUpDanglingCalls(result: MethodResult): void {
FlutterWebAuthPlugin.callbacks.forEach((danglingResult: MethodResult) => {
danglingResult.error("CANCELED", "User canceled login", null);
});
FlutterWebAuthPlugin.callbacks.clear();
result.success(null);
}
4.2 执行流程
1. 遍历 callbacks Map 中所有 pending 的 MethodResult
2. 对每个 result 返回 CANCELED 错误
3. 清空整个 Map
4. 返回 success(null) 给 Dart 层的 _cleanUpDanglingCalls 调用
4.3 forEach 的参数
FlutterWebAuthPlugin.callbacks.forEach((danglingResult: MethodResult) => {
danglingResult.error("CANCELED", "User canceled login", null);
});
Map 的 forEach 回调参数是 (value, key, map)。这里只用了 value(MethodResult),key(scheme)被忽略了。
4.4 error 参数
danglingResult.error("CANCELED", "User canceled login", null);
// ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^^
// 错误码 错误消息 详情
| 参数 | 值 | Dart 层对应 |
|---|---|---|
| code | “CANCELED” | PlatformException.code |
| message | “User canceled login” | PlatformException.message |
| details | null | PlatformException.details |
4.5 Dart 层的捕获
try {
final result = await FlutterWebAuth.authenticate(...);
} on PlatformException catch (e) {
if (e.code == 'CANCELED') {
// 用户取消了登录
print('用户取消: ${e.message}');
}
}
五、result.notImplemented() 的防御处理
5.1 实现
} else {
result.notImplemented();
}
5.2 触发场景
| 场景 | 说明 |
|---|---|
| Dart 层调用了不存在的方法 | 代码错误 |
| 版本不匹配 | Dart 层新增了方法,原生层没更新 |
| 其他插件的消息误发 | 通道名称冲突(极罕见) |
5.3 与 secure_application 的对比
// flutter_web_auth:返回 notImplemented
result.notImplemented();
// secure_application:返回 success(true)
default:
result.success(true);
break;
| 处理方式 | 含义 | 适用场景 |
|---|---|---|
| notImplemented() | 明确告诉调用者"这个方法不存在" | 严格的 API 契约 |
| success(true) | 静默忽略未知方法 | 宽松的兼容策略 |
💡 flutter_web_auth 选择了更严格的方式。如果 Dart 层调用了不存在的方法,会收到 MissingPluginException,开发者能立即发现问题。
六、authenticate 方法的异步特性
6.1 与其他方法的区别
// authenticate:不立即返回结果
this.authenticate(url, callbackUrlScheme, result);
// result 被存入 callbacks Map,等待 onNewWant 时才调用 result.success()
// cleanUpDanglingCalls:立即返回结果
this.cleanUpDanglingCalls(result);
// result.success(null) 在方法内部立即调用
6.2 MethodResult 的延迟使用
| 方法 | result 使用时机 | 延迟 |
|---|---|---|
| authenticate | onNewWant 回调时 | 秒到分钟 |
| cleanUpDanglingCalls | 方法内部 | 即时 |
6.3 延迟使用的风险
风险:如果 result 在使用前被 GC 回收怎么办?
答:不会。callbacks Map 持有 result 的引用,
只要 Map 中有这个 entry,result 就不会被 GC。
callbacks.set(scheme, result); // Map 持有引用
// ... 等待 ...
callbacks.get(scheme); // 引用仍然有效
七、日志记录
7.1 当前的日志点
onMethodCall(call: MethodCall, result: MethodResult): void {
console.info(TAG, `onMethodCall: ${call.method}`);
if (call.method == "authenticate") {
console.info(TAG, `authenticate called with url=${url}, scheme=${callbackUrlScheme}`);
// ...
}
}
7.2 日志级别使用
| 操作 | 级别 | 示例 |
|---|---|---|
| 方法调用 | info | onMethodCall: authenticate |
| 参数记录 | info | url=..., scheme=... |
| 成功操作 | info | openLink succeeded |
| 失败操作 | error | openLink failed: ... |
7.3 安全注意事项
// ⚠️ 当前实现会把完整 URL 打印到日志中
console.info(TAG, `authenticate called with url=${url}`);
// URL 中可能包含 client_id 等敏感信息
// 生产环境建议只打印 Scheme,不打印完整 URL
console.info(TAG, `authenticate called with scheme=${callbackUrlScheme}`);
📌 生产环境中应该避免在日志中打印完整的认证 URL,因为 URL 中可能包含 client_id、state 等敏感参数。
总结
本文分析了 flutter_web_auth 的 onMethodCall 实现:
- 两个方法:authenticate(异步)和 cleanUpDanglingCalls(同步)
- 参数提取:call.argument() + as 类型断言
- preferEphemeral 忽略:OpenHarmony 不支持隐私浏览
- notImplemented():严格的 API 契约,未知方法报错
- 日志安全:生产环境避免打印完整 URL
下一篇我们讲 Dangling Calls 清理机制——用户取消认证时的完整处理流程。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:

MethodChannel 方法分发架构
更多推荐

所有评论(0)