142 lines
5.5 KiB
Markdown
142 lines
5.5 KiB
Markdown
# 架构设计
|
||
|
||
## 整体架构
|
||
|
||
```text
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ apps/aixue apps/test apps/yunxiao apps/... │ 品牌应用层
|
||
│ main.dart 只负责传入 ShellEnvironment │
|
||
├────────────────────────────────────────────────────────────┤
|
||
│ web_shell_core │ 核心库
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||
│ │ config │ │ engine │ │ bridge │ │
|
||
│ │ 启动配置 │ │ 兼容引擎 │ │ JS 桥接 │ │
|
||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||
│ │ services │ │ ui │ │ testing │ │
|
||
│ │ 宿主服务 │ │ 壳层界面 │ │ 测试钩子 │ │
|
||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||
├────────────────────────────────────────────────────────────┤
|
||
│ CoreShellActivity (Java) │ 原生层
|
||
│ 进程隔离 · WebView 信息查询 · 深度重置 │
|
||
└────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
## 配置分层
|
||
|
||
### 启动配置
|
||
|
||
启动配置负责影响首屏加载行为,当前拆成两层:
|
||
|
||
1. 本地默认启动配置:`assets/config/bootstrap.json`
|
||
2. 远程启动配置:`bootstrap_config_url`
|
||
|
||
字段示例:
|
||
|
||
```json
|
||
{
|
||
"initialUrl": "https://example.com/login",
|
||
"preferredOrientations": ["portraitUp", "portraitDown"]
|
||
}
|
||
```
|
||
|
||
### 升级配置
|
||
|
||
升级配置仅用于版本检查,不参与首页地址解析,单独由 `upgrade_config_url` 拉取。
|
||
|
||
字段示例:
|
||
|
||
```json
|
||
{
|
||
"versionName": "1.0.1",
|
||
"version": 101,
|
||
"isForce": 0,
|
||
"remark": "1. 修复已知问题",
|
||
"filePath": "https://example.com/app-release.apk",
|
||
"fileSize": 25000
|
||
}
|
||
```
|
||
|
||
## 核心流程
|
||
|
||
### 1. 启动流程
|
||
|
||
```text
|
||
main()
|
||
→ runShellApp(env)
|
||
→ WidgetsFlutterBinding.ensureInitialized()
|
||
→ 读取本地默认启动配置 bootstrapConfigAsset
|
||
→ 拉取远程启动配置 bootstrapConfigUrl(可选,失败走缓存)
|
||
→ 合并 initialUrl / preferredOrientations
|
||
→ setupConfigUrl(upgradeConfigUrl)
|
||
→ _initializeUrls()
|
||
→ SystemChrome.setPreferredOrientations(...)
|
||
→ 进入沉浸式模式
|
||
→ runApp(ShellApp)
|
||
→ Android → WebShellPage
|
||
→ 非 Android → UnsupportedPlatformPage
|
||
```
|
||
|
||
### 2. WebView 启动与恢复
|
||
|
||
```text
|
||
WebShellPage.initState()
|
||
→ 查询 Android WebView 信息(SDK / 包名 / 版本号)
|
||
→ 生成兼容性策略(renderModes / useWideViewPort / aggressiveRecovery)
|
||
→ 创建 WebView
|
||
→ 首帧后加载 _initialUrl
|
||
→ 同时异步执行 checkVersion(context)
|
||
→ 主帧成功 → 注入 Bridge
|
||
→ 主帧失败 → 展示 ErrorOverlay,不再白屏
|
||
→ 启动超时 → 切换渲染模式 / 深度清理 / 自动重试
|
||
```
|
||
|
||
### 3. JS Bridge 协议
|
||
|
||
```text
|
||
H5 页面 Flutter 壳
|
||
│ │
|
||
│ AppShellChannel.postMessage │
|
||
│──────────────────────────────→ │ 解析 action + payload
|
||
│ │ 执行 handler
|
||
│ __appShellReceiveResponse │
|
||
│←────────────────────────────── │ 返回 { requestId, success, data/error }
|
||
```
|
||
|
||
当前支持 12 个 Action:
|
||
|
||
| Action | 说明 |
|
||
|---|---|
|
||
| `pickImage` | 从图库选图 |
|
||
| `captureImage` | 相机拍照 |
|
||
| `pickFile` | 文件选择 |
|
||
| `openExternal` | 打开外部应用 |
|
||
| `requestPermissions` | 请求系统权限 |
|
||
| `reloadPage` | 重新加载当前页面 |
|
||
| `goBack` | 返回上一页 |
|
||
| `closeApp` | 关闭应用 |
|
||
| `getDeviceInfo` | 获取设备信息 |
|
||
| `getNetworkStatus` | 获取网络状态 |
|
||
| `showToast` | 展示 Toast |
|
||
| `setStatusBar` | 设置状态栏样式 |
|
||
|
||
## 兼容性策略
|
||
|
||
| 条件 | 渲染模式 | 恢复策略 |
|
||
|---|---|---|
|
||
| SDK ≥ 29 + 新版 WebView | texture 优先 | 标准恢复 |
|
||
| SDK ≤ 28 或旧版 WebView | hybrid 优先 | 激进恢复 |
|
||
| F136A 设备 | hybrid 优先 | 激进恢复 + 建议更新 WebView |
|
||
|
||
## 新增品牌流程
|
||
|
||
1. 新建 `flavors/品牌名.yaml`
|
||
2. 在 `flavors/品牌名/` 放置品牌资源
|
||
3. 执行 `dart run tool/generate_app.dart 品牌名`
|
||
4. 生成器自动产出:
|
||
- `apps/品牌名/lib/main.dart`
|
||
- `apps/品牌名/assets/config/bootstrap.json`
|
||
- `apps/品牌名/assets/branding/*`
|
||
- Android 图标、启动页、签名配置
|
||
5. 构建 APK:`cd apps/品牌名 && flutter build apk --release`
|