Flutter三方库适配OpenHarmony【flutter_web_auth】— Android 端 Chrome Custom Tabs 实现分析

前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

在适配 OpenHarmony 之前,先看看 Android 端是怎么做的。Android 用 Chrome Custom Tabs 打开认证页面,用 CallbackActivity + Intent Filter 接收回调。这套方案是 OpenHarmony 适配的主要参照物——很多设计决策都是从 Android 映射过来的。

一、Chrome Custom Tabs 与 WebView 的区别

1.1 为什么不用 WebView

请添加图片描述

用户可能已经在 Chrome 中登录了 Google 账号。如果用 Chrome Custom Tabs,用户不需要重新输入密码——直接点击"允许"就行。这对用户体验的提升是巨大的。

WebView:用户每次都要输入用户名和密码 Chrome Custom Tabs:用户可能只需要点一下"允许" 
💡 这也是 OpenHarmony 用系统浏览器(openLink)而不是 WebView 的原因——系统浏览器共享用户的登录状态。

二、CallbackActivity 的 Intent Filter 配置

2.1 AndroidManifest.xml 配置

<activityandroid:name="com.linusu.flutter_web_auth.CallbackActivity"android:exported="true"><intent-filterandroid:label="flutter_web_auth"><actionandroid:name="android.intent.action.VIEW"/><categoryandroid:name="android.intent.category.DEFAULT"/><categoryandroid:name="android.intent.category.BROWSABLE"/><dataandroid:scheme="YOUR_CALLBACK_URL_SCHEME_HERE"/></intent-filter></activity>

2.2 各字段含义

字段作用
action.VIEW查看操作表示这个 Activity 可以处理"查看"类型的 Intent
category.DEFAULT默认类别允许隐式 Intent 启动
category.BROWSABLE可浏览允许从浏览器启动
data.scheme自定义 Scheme匹配特定 URL Scheme

2.3 工作流程

1. 浏览器重定向到 myapp://callback?code=abc123 2. Android 系统查找能处理 myapp:// 的 Activity 3. 找到 CallbackActivity(因为 Intent Filter 匹配) 4. CallbackActivity 启动,获取 Intent 中的 URI 5. CallbackActivity 把 URI 传给 FlutterWebAuthPlugin 6. Plugin 通过 MethodChannel 返回给 Dart 

2.4 与 OpenHarmony 的对应关系

AndroidOpenHarmony
CallbackActivityEntryAbility(复用主 Ability)
Intent Filterskills 配置
android:schemeuris.scheme
action.VIEWohos.want.action.viewData
category.BROWSABLEentity.system.browsable

三、FLAG_ACTIVITY_NO_HISTORY 与 preferEphemeral

3.1 preferEphemeral 在 Android 上的实现

// Android 端代码(简化)val intent = CustomTabsIntent.Builder().build()if(preferEphemeral){ intent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)} intent.launchUrl(context, Uri.parse(url))

3.2 FLAG_ACTIVITY_NO_HISTORY 的效果

有 FLAG无 FLAG
认证页面不保留在任务栈中认证页面保留在任务栈中
用户按返回键直接回到 App用户按返回键回到认证页面
不留浏览历史留浏览历史

3.3 在 OpenHarmony 上的对应

// OpenHarmony 当前实现:没有处理 preferEphemeralconst url = call.argument('url')asstring;// preferEphemeral 参数被忽略了 context.openLink(url);
📌 当前限制:OpenHarmony 的 openLink API 不支持"不留历史"的选项。preferEphemeral 参数在 OpenHarmony 上没有效果。未来可以通过 Want 的 flags 参数来实现类似功能。

四、从浏览器回调到 Flutter 的完整数据流

4.1 Android 数据流

浏览器重定向 ↓ Android 系统匹配 Intent Filter ↓ CallbackActivity.onCreate(intent) ↓ intent.data → URI 字符串 ↓ FlutterWebAuthPlugin.callbacks[scheme].success(uri) ↓ MethodChannel → Dart ↓ FlutterWebAuth.authenticate() 返回 uri 

4.2 OpenHarmony 数据流

浏览器重定向 ↓ OpenHarmony 系统匹配 Want skills ↓ EntryAbility.onNewWant(want) ↓ FlutterWebAuthPlugin.onNewWant(want) ↓ want.uri → URI 字符串 ↓ FlutterWebAuthPlugin.callbacks[scheme].success(uri) ↓ MethodChannel → Dart ↓ FlutterWebAuth.authenticate() 返回 uri 

4.3 关键差异

差异点AndroidOpenHarmony
回调接收者独立的 CallbackActivity复用 EntryAbility
数据来源intent.datawant.uri
触发方式Activity 自动启动onNewWant 回调
需要宿主配合只需配置 Manifest需要写代码调用 onNewWant

五、Android 端 dangling calls 清理

5.1 问题场景

1. 用户点击登录 → 浏览器打开 2. 用户在浏览器中按返回键 → 回到 App 3. authenticate() 的 Future 还在等待 → 永远不会完成 

5.2 Android 的清理机制

// Android 端funcleanUpDanglingCalls(){ callbacks.forEach{(_, result)-> result.error("CANCELED","User canceled login",null)} callbacks.clear()}

5.3 触发时机

App 回到前台(resumed) ↓ Dart: _OnAppLifecycleResumeObserver.didChangeAppLifecycleState(resumed) ↓ Dart: _cleanUpDanglingCalls() ↓ Dart → Native: invokeMethod('cleanUpDanglingCalls') ↓ Native: 遍历 callbacks,返回 CANCELED 

5.4 OpenHarmony 的实现

// OpenHarmony 端:完全相同的逻辑privatecleanUpDanglingCalls(result: MethodResult):void{ FlutterWebAuthPlugin.callbacks.forEach((danglingResult: MethodResult)=>{ danglingResult.error("CANCELED","User canceled login",null);}); FlutterWebAuthPlugin.callbacks.clear(); result.success(null);}
💡 这是 Dart 层驱动的清理机制。不管原生端是 Android 还是 OpenHarmony,清理逻辑都是 Dart 层的 Observer 触发的。原生端只需要实现 cleanUpDanglingCalls 方法就行。

六、Result 生命周期管理

6.1 MethodResult 的生命周期

创建:onMethodCall 中接收 result 参数 ↓ 存储:callbacks[scheme] = result ↓ 使用:result.success(uri) 或 result.error(...) ↓ 销毁:从 callbacks Map 中删除 

6.2 一个 Result 只能用一次

// ✅ 正确:用完就删const pendingResult = FlutterWebAuthPlugin.callbacks.get(scheme); FlutterWebAuthPlugin.callbacks.delete(scheme);// 先删 pendingResult.success(uri);// 再用// ❌ 错误:重复使用 pendingResult.success(uri); pendingResult.success(uri);// 第二次调用会崩溃

6.3 防止 Result 泄漏

场景处理方式
正常回调onNewWant 中 success + delete
用户取消cleanUpDanglingCalls 中 error + clear
插件销毁onDetachedFromEngine 中不处理(Dart 层会清理)

七、Android 实现的设计启示

7.1 对 OpenHarmony 适配的启示

Android 设计OpenHarmony 对应启示
CallbackActivityEntryAbility.onNewWant回调入口
Intent Filterskills 配置深度链接匹配
static callbacksstatic callbacks跨实例数据共享
cleanUpDanglingCallscleanUpDanglingCalls用户取消处理

7.2 OpenHarmony 的额外挑战

  1. 没有独立的 CallbackActivity:必须在 EntryAbility 中手动集成
  2. openLink 是异步的:Android 的 startActivity 是同步的
  3. 需要降级方案:openLink 失败时要 fallback 到 startAbility

总结

本文分析了 Android 端的 Chrome Custom Tabs 实现:

  1. Chrome Custom Tabs:共享 Cookie、安全沙箱、用户信任度高
  2. CallbackActivity:通过 Intent Filter 捕获深度链接回调
  3. preferEphemeral:FLAG_ACTIVITY_NO_HISTORY 不留浏览历史
  4. dangling calls:Dart 层 Observer 驱动的清理机制
  5. Result 生命周期:一次性使用,用完即删

下一篇我们看 iOS/macOS 端的 ASWebAuthenticationSession 实现。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!

相关资源:

Read more

2026年主流AI生成PPT工具横评:6款实测,谁是你的效率搭档?

2026年主流AI生成PPT工具横评:6款实测,谁是你的效率搭档?

原创声明:本文为作者原创,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 摘要:AI生成PPT工具正成为职场办公的重要辅助手段。本文基于2026年3月的实测体验,对市面上6款主流AI PPT工具进行客观评测,从核心功能、技术特点、适用场景、费用机制等维度展开分析,涵盖7牛AI PPT、百度文库PPT、Kimi PPT、Gamma、讯飞智文、WPS AI等产品。不吹不黑,只讲实话,帮助读者根据自身需求找到合适的工具。 关键词:AI生成PPT;AI做PPT;工具横评;办公效率;智能办公 一、引言:AI做PPT,如今发展到哪一步了? 凌晨三点还在调整PPT字体间距?因为领导一句“逻辑不对”就要推翻重排版式?这种被PPT支配的日子,很多职场人都经历过。 数据显示,普通职场人年均花费87小时在幻灯片制作上,其中42%的时间耗在排版、

人工智能:大语言模型(LLM)原理与应用实战

人工智能:大语言模型(LLM)原理与应用实战

人工智能:大语言模型(LLM)原理与应用实战 1.1 本章学习目标与重点 💡 学习目标:掌握大语言模型的核心原理、训练流程与微调方法,学会基于开源大语言模型完成定制化对话与文本生成任务。 💡 学习重点:理解大语言模型的Transformer decoder-only架构,掌握指令微调与RLHF技术,能够使用LoRA高效微调开源LLM。 1.2 大语言模型的核心概念与发展历程 1.2.1 什么是大语言模型 💡 大语言模型(Large Language Model, LLM)是参数量达到十亿级甚至万亿级的Transformer-based模型。它通过在海量文本数据上进行预训练,学习语言的语法、语义、常识和推理能力。 LLM的核心能力包括文本生成、理解、翻译、摘要、问答等。它可以处理复杂的自然语言任务,无需针对每个任务单独设计模型结构。 LLM与传统NLP模型的核心区别: * 参数量级:传统模型参数量通常在千万级,LLM参数量可达十亿到万亿级。 * 训练数据:传统模型依赖标注数据,LLM使用海量无标注文本进行预训练。 * 能力边界:传统模型只能处理单一任务,LL

『告别手工测试:AI 自动化测试覆盖 90% 场景的秘诀』

『告别手工测试:AI 自动化测试覆盖 90% 场景的秘诀』

在 AI 技术飞速渗透各行各业的当下,我们早已告别 “谈 AI 色变” 的观望阶段,迈入 “用 AI 提效” 的实战时代 💡。无论是代码编写时的智能辅助 💻、数据处理中的自动化流程 📊,还是行业场景里的精准解决方案 ,AI 正以润物细无声的方式,重构着我们的工作逻辑与行业生态 🌱。今天,我想结合自身实战经验,带你深入探索 AI 技术如何打破传统工作壁垒 🧱,让 AI 真正从 “概念” 变为 “实用工具” ,为你的工作与行业发展注入新动能 ✨。 文章目录 * 告别手工测试:AI 自动化测试覆盖 90% 场景的秘诀 🤖🧪 * 一、引言:从手工到AI,测试革命的浪潮 🌊🌊 * 1. 传统手工测试的困境 ⚠️ * 2. 自动化测试的初步尝试 🤖 * 3. AI驱动自动化测试的崛起 🌟🤖 * 二、AI自动化测试的关键技术栈 🧠⚙️ * 1.

AskGo:免费使用顶级AI的宝藏网站(Gemini 3、GPT 5.1、DeepSeek)

AskGo:免费使用顶级AI的宝藏网站(Gemini 3、GPT 5.1、DeepSeek)

这几年,AI大模型可谓是极速迭代,在激烈的竞争下,国内的AI大模型能力也有了质的飞跃,如通义千问、豆包、GLM、Kimi等。 但其实国外的AI大模型目前依然呈领先趋势,只是很多人在国内无法使用。 那么今天给大家推荐一个能够同时使用国内外顶级AI的网站——AskGo! AskGo集成了ChatGPT、DeepSeek、Gemini、Claude、Grok等数十个顶尖大模型,覆盖聊天、搜索、深度阅读、创意写作、程序开发、专业翻译、图像生成及视频生成等全场景。无需再做选择题,你可以随时利用最前沿的AI技术解决复杂问题。 AskGo为您提供「一站式AI」综合解决方案: ✅ 国内直接使用数十款顶级AI。包含GPT 5.1、Gemini 3 pro、Claude 4.5、Grok 4.1、DeepSeek满血版、Nano Banana Pro、GPT-4o绘图、Sora2、Veo3.1等顶级模型。