# 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