# YX App Upgrade Flutter
一款轻量、现代且易用的 Flutter 应用内更新插件。支持 Android 的"下载-安装"全流程,iOS 自动跳转 App Store。提供「一键检查更新」与「静默检查 + 用户决定」两种常见用法,并内置完善的权限处理与安装策略。
## ✨ 特性
- **🎯 智能平台适配**:Android 直下直装,iOS 跳转 App Store
- **🧠 智能辅助工具**:内置 `UpgradeAuxiliaryUtils`,支持**设备类型自动识别**与**"稍后更新"状态记忆**(同一版本被跳过不再打扰)。
- **🔄 灵活的更新策略**:
- **一键检查**:自动拉取、对比版本、弹窗提示
- **静默检查**:后台获取更新信息,适合冷启动或用户主动点击前的预检查
- **🎨 现代化 UI**:
- Material 风格对话框
- **📝 富文本支持**:更新日志支持粗体、斜体、代码块、高亮等格式
- 进度与状态可视化
- **🛡️ 权限适配完善**:针对不同 Android 版本的存储、安装、通知权限自动处理
- **🌐 网络可配置**:证书校验、超时、默认方法、Headers 等
- **🔧 安装策略灵活**:系统流程/预检查权限/智能策略可选
- **🏪 应用市场支持**:支持多应用市场白名单,智能检测设备已安装的市场
- **📦 多种更新方式**:应用市场、浏览器下载、应用内下载
## 📦 安装
在 `pubspec.yaml` 中添加依赖:
```yaml
dependencies:
yx_app_upgrade_flutter: ^1.0.0
```
## 🚀 快速开始
### 方式一:使用辅助工具检查(推荐)
使用 `UpgradeAuxiliaryUtils` 可以自动处理设备类型判断,并记住用户的"稍后更新"选择(若用户对当前版本点击了稍后更新,下次检查将自动跳过,避免重复打扰)。
```dart
import 'package:yx_app_upgrade_flutter/yx_app_upgrade_flutter.dart';
void checkUpdate(BuildContext context) {
UpgradeAuxiliaryUtils.instance.initiateVersionCheck(
context,
// upType: 1 为 Android, 2 为 iOS
future: (int upType) async {
// 模拟请求 API
// final response = await api.checkVersion(type: upType);
return AppUpgradeVersion(
versionName: "1.2.0",
versionBuildNumber: 102,
downloadUrl: "https://example.com/app.apk",
updateContent: "1. 新增功能\n2. 修复Bug",
// ... 其他配置
);
},
// 可选配置
showNoUpdateToast: true, // 无更新时是否提示
config: UpgradeConfig.production, // 指定环境配置
);
}
```
### 方式二:基础 API (AppUpgradeSimple)
如果您需要更底层的控制,或者不需要"稍后更新"的记忆功能,可以直接使用核心类 `AppUpgradeSimple`。
#### 1. 一键检查更新
```dart
import 'package:yx_app_upgrade_flutter/app_upgrade_simple.dart';
// ...
AppUpgradeSimple.instance.checkUpdate(
context: context,
future: () async {
// 调用 API 获取版本信息
return AppUpgradeVersion(
// ...
);
},
);
```
#### 2. 静默检查 + 由用户决定
此方式适用于 App 启动时在后台静默检查,仅在有更新时(如显示红点)提示用户。
```dart
// 1. 静默检查更新(不显示任何 UI)
final upgradeInfo = await AppUpgradeSimple.instance.silentCheckUpdate(
future: () async {
return AppUpgradeVersion(...);
},
);
// 2. 根据结果处理
if (upgradeInfo != null && upgradeInfo.hasUpdate) {
print('发现新版本: ${upgradeInfo.versionName}');
// 显示红点,或者在用户点击"检查更新"按钮时调用:
AppUpgradeSimple.instance.showPreparedUpgrade(
context: context,
info: upgradeInfo,
);
}
```
### 常用配置
```dart
// 预设配置:
AppUpgradeSimple.instance.configure(UpgradeConfig.development); // 开发模式(详细日志+提示)
AppUpgradeSimple.instance.configure(UpgradeConfig.production); // 生产模式(静默+性能优化)
// 自定义配置:
AppUpgradeSimple.instance.configure(const UpgradeConfig(
showNoUpdateToast: true,
autoInstall: false,
installTimeout: 60,
enableDebugLog: true,
requireInstallPermission: false,
));
```
## 🎨 UI 能力与富文本
### 富文本更新日志
更新内容 (`updateContent`) 支持简单的 Markdown 风格富文本:
- **粗体**:`**重要内容**`
- **斜体**:`__斜体内容__`
- **代码块**:`` `version 2.0` ``
- **高亮**:`[特别注意]`
支持嵌套组合使用,例如:
- `**[特别注意]**`
- `__**重要说明**__`
- `请使用 \`version 2.0\` 进行灰度验证`
```text
1. 新增 **深色模式** 支持
2. 修复 `Login` 页面崩溃问题
3. [推荐] 性能大幅优化
```
### 头部说明块 `/{ ... /}`
从当前版本开始,`updateContent` 支持一个可选的头部说明区域,用于展示“本次版本概述 / 重点提示 / 总结说明”等内容。
头部块语法:
- 起始标记:`/{`
- 结束标记:`/}`
- 头部块是可选的
- 头部块可以为空
- 头部块内继续支持现有富文本标记与嵌套组合
#### 多行写法
```text
/{
本次 **V2.2.0** 版本围绕[使用体验]与[学习管理]进行了多项优化。
__请优先关注__ 工作录入与成长中心改动。
/}
1. 新增草稿箱功能
2. 优化多账号登录机制
```
#### 单行写法
```text
/{ 本次版本重点优化登录体验与录入效率 /}
1. 新增草稿箱功能
2. 修复已知问题
```
#### 空头部块写法
```text
/{ /}
1. 第一条更新说明
2. 第二条更新说明
```
#### 头部块中的嵌套示例
```text
/{
**重要内容**
__[特别注意]__
`version 2.0`
普通说明与 **[高亮重点]** 混合展示
/}
```
### 推荐的 `updateContent` 写法
建议服务端直接返回结构清晰的字符串,头部概述和正文分开:
```text
/{
本次 **V2.2.0** 版本围绕[使用体验]、[账号安全]、[家校联动]、[学习管理]等方面进行多项优化与功能新增,具体更新内容如下:
/}
1. 工作录入新增**草稿箱功能**,录入内容自动暂存;
2. 优化**多账号登录机制**,同一手机号绑定多个账号时可手动选择;
3. 全新上线**家校互动板块**;
4. **成长中心**全面调整优化。
```
### 解析规则说明
- 只有当 `updateContent` 的第一段内容以 `/{` 开始时,才会被识别为头部说明块
- 头部说明块中的内容会单独显示在正文上方
- 头部中的 `** / __ / \` / []` 标记会继续走现有富文本渲染逻辑
- 如果正文行本身已经包含 `1.`、`一、`、`-`、`•` 等前缀,插件不会再额外补一个圆点,避免双重列表样式
- 如果缺少闭合标记 `/}`,插件会回退为普通正文处理,不会抛出异常
### 调试与预解析
如果你希望在展示前先检查解析结果,可以使用:
```dart
final parsed = AppUpgradeSimple.parseUpdateContent(updateContent);
debugPrint('hasExplicitHeaderBlock: ${parsed.hasExplicitHeaderBlock}');
debugPrint('header: ${parsed.header}');
debugPrint('bodyItems: ${parsed.bodyItems.map((e) => e.text).toList()}');
```
返回结果说明:
- `parsed.header`:头部说明内容
- `parsed.hasExplicitHeaderBlock`:是否显式使用了 `/{ ... /}` 头部块
- `parsed.bodyItems`:正文条目列表
- `parsed.bodyItems[i].hasLeadingMarker`:该条正文是否已经自带列表前缀
### 对话框特性
- **发现新版本**(强制/非强制)
- **版本信息卡片**
- **下载进度展示**
- **安装状态检测**
## ⚙️ Android 配置
### 1) 权限
在 `android/app/src/main/AndroidManifest.xml` 中添加:
```xml
```
### 2) FileProvider 路径
创建 `android/app/src/main/res/xml/file_paths.xml`:
```xml
```
## 📡 服务端返回协议
服务端需要返回包含以下字段的 JSON,并在前端转换为 `AppUpgradeVersion` 对象:
```json
{
"isForceUpdate": false,
"versionBuildNumber": 101,
"versionName": "1.0.1",
"updateContent": "1. 新增 **深色模式**\n2. 修复 `Bug`",
"downloadUrl": "https://your-cdn.com/app-release.apk",
"appStoreUrl": "https://apps.apple.com/app/id123456789",
"apkSize": 25165824,
"apkMd5": "d41d8cd98f00b204e9800998ecf8427e",
"appMarkets": ["huawei", "xiaomi", "oppo"],
"supportedMethods": ["market", "browser", "inApp"]
}
```
## 🔧 进阶能力
### 1) 网络配置
```dart
// 自动选择
AppUpgradePlugin().configureHttp(HttpConfig.auto);
// 手动配置
AppUpgradePlugin().configureHttp(const HttpConfig(
ignoreCertificate: false,
enableLog: true,
connectTimeout: 30,
headers: {'Authorization': 'Bearer xxx'},
));
```
### 2) 预下载 APK
```dart
final apkPath = await AppUpgradeSimple.instance.preDownloadApk(
url: 'https://...',
onProgress: (progress) => print('${progress.percentage}%'),
);
```
## 🤝 贡献
欢迎提交 Issue 与 Pull Request!
## 📄 许可证
MIT License