295 lines
9.6 KiB
Markdown
295 lines
9.6 KiB
Markdown
# YX App Upgrade Flutter
|
||
|
||
一款轻量、现代且易用的 Flutter 应用内更新插件。支持 Android 的"下载-安装"全流程,iOS 自动跳转 App Store。提供「一键检查更新」与「静默检查 + 用户决定」两种常见用法,并内置完善的权限处理与安装策略。
|
||
|
||
## ✨ 特性
|
||
|
||
- **🎯 智能平台适配**:Android 直下直装,iOS 跳转 App Store
|
||
- **🔄 灵活的更新策略**:
|
||
- **一键检查**:自动拉取、对比版本、弹窗提示
|
||
- **静默检查**:后台获取更新信息,适合冷启动或用户主动点击前的预检查
|
||
- **🎨 现代化 UI**:
|
||
- Material 风格对话框
|
||
- **📝 富文本支持**:更新日志支持粗体、斜体、代码块、高亮等格式
|
||
- 进度与状态可视化
|
||
- **🛡️ 权限适配完善**:针对不同 Android 版本的存储、安装、通知权限自动处理
|
||
- **🌐 网络可配置**:证书校验、超时、默认方法、Headers 等
|
||
- **🔧 安装策略灵活**:系统流程/预检查权限/智能策略可选
|
||
- **🏪 应用市场支持**:支持多应用市场白名单,智能检测设备已安装的市场
|
||
- **📦 多种更新方式**:应用市场、浏览器下载、应用内下载
|
||
|
||
## 📦 安装
|
||
|
||
在 `pubspec.yaml` 中添加依赖:
|
||
|
||
```yaml
|
||
dependencies:
|
||
yx_app_upgrade_flutter: ^1.0.0
|
||
```
|
||
|
||
## 🚀 快速开始
|
||
|
||
### 方式一:一键检查更新(推荐)
|
||
|
||
这是最简单的方式,一行代码即可完成检查更新并显示升级对话框:
|
||
|
||
```dart
|
||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin.dart';
|
||
|
||
void checkUpdate(BuildContext context) {
|
||
// 可选:一次性配置常用选项
|
||
AppUpgradeSimple.instance.configure(
|
||
const UpgradeConfig(
|
||
showNoUpdateToast: true,
|
||
autoInstall: false,
|
||
),
|
||
);
|
||
|
||
// 一行调用,自动拉取并展示升级对话框
|
||
AppUpgradeSimple.instance.checkUpdate(
|
||
context: context,
|
||
future: () async {
|
||
// 调用您的 API 获取版本信息
|
||
final response = await http.get('https://your-api.com/check-update');
|
||
final data = json.decode(response.body);
|
||
|
||
// 返回 AppUpgradeVersion 对象
|
||
return AppUpgradeVersion(
|
||
versionName: data['versionName'],
|
||
versionBuildNumber: data['versionBuildNumber'],
|
||
isForce: data['isForceUpdate'] ?? false,
|
||
updateContent: data['updateContent'],
|
||
downloadUrl: data['downloadUrl'],
|
||
appStoreUrl: data['appStoreUrl'],
|
||
apkSize: data['apkSize'],
|
||
apkMd5: data['apkMd5'],
|
||
// 应用市场配置
|
||
appMarkets: (data['appMarkets'] as List?)
|
||
?.map((e) => AppMarket.fromString(e))
|
||
.toList(),
|
||
// 支持的更新方式
|
||
supportedMethods: [
|
||
AppUpgradeMethod.market,
|
||
AppUpgradeMethod.browser,
|
||
AppUpgradeMethod.inApp,
|
||
],
|
||
);
|
||
},
|
||
);
|
||
}
|
||
```
|
||
|
||
### 方式二:静默检查 + 由用户决定
|
||
|
||
此方式适用于:
|
||
1. **App 启动时**:在后台静默检查是否有更新,如果有则在合适的时机(如用户点击"版本更新"按钮时)展示,避免打断用户操作。
|
||
2. **红点提示**:检查到有更新时仅显示红点,用户点击后才弹出对话框。
|
||
|
||
```dart
|
||
// 1. 静默检查更新(不显示任何 UI)
|
||
final upgradeInfo = await AppUpgradeSimple.instance.silentCheckUpdate(
|
||
future: () async {
|
||
// 调用您的 API
|
||
return AppUpgradeVersion(...);
|
||
},
|
||
);
|
||
|
||
// 2. 根据结果处理
|
||
if (upgradeInfo != null && upgradeInfo.hasUpdate) {
|
||
// 有新版本,可以显示红点或在用户点击时调用弹窗
|
||
print('发现新版本: ${upgradeInfo.versionName}');
|
||
|
||
// 在需要展示弹窗的时机(如用户点击按钮):
|
||
AppUpgradeSimple.instance.showPreparedUpgrade(
|
||
context: context,
|
||
info: upgradeInfo, // 传入刚才获取的 info
|
||
);
|
||
}
|
||
```
|
||
|
||
### 常用配置
|
||
|
||
```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` ``
|
||
- **高亮**:`[特别注意]`
|
||
|
||
示例:
|
||
```text
|
||
1. 新增 **深色模式** 支持
|
||
2. 修复 `Login` 页面崩溃问题
|
||
3. [推荐] 性能大幅优化
|
||
```
|
||
|
||
### 对话框特性
|
||
|
||
- **发现新版本**(强制/非强制)
|
||
- 强制更新:不可关闭,必须更新
|
||
- 非强制更新:可稍后更新,支持后台下载
|
||
- **版本信息卡片**:显示当前版本、新版本、APK 大小
|
||
- **下载进度展示**:实时显示下载进度百分比和状态
|
||
- **安装状态检测**:自动检测安装结果,支持重试
|
||
|
||
## ⚙️ Android 配置
|
||
|
||
### 1) 权限
|
||
|
||
在 `android/app/src/main/AndroidManifest.xml` 中添加:
|
||
|
||
```xml
|
||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||
<uses-permission android:name="android.permission.INTERNET" />
|
||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||
<!-- Android 13+ 通知权限(可选) -->
|
||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||
<!-- Android 9 写储存权限(SDK 28 及以下需要) -->
|
||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||
|
||
<application>
|
||
<!-- FileProvider(Android 7.0+ APK 安装必需) -->
|
||
<provider
|
||
android:name="androidx.core.content.FileProvider"
|
||
android:authorities="${applicationId}.fileprovider"
|
||
android:exported="false"
|
||
android:grantUriPermissions="true">
|
||
<meta-data
|
||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||
android:resource="@xml/file_paths" />
|
||
</provider>
|
||
</application>
|
||
|
||
<!-- Android 11+ 查询声明:允许打开浏览器处理 HTTP/HTTPS URL -->
|
||
<queries>
|
||
<intent>
|
||
<action android:name="android.intent.action.VIEW" />
|
||
<data android:scheme="https" />
|
||
</intent>
|
||
<intent>
|
||
<action android:name="android.intent.action.VIEW" />
|
||
<data android:scheme="http" />
|
||
</intent>
|
||
</queries>
|
||
</manifest>
|
||
```
|
||
|
||
### 2) FileProvider 路径
|
||
|
||
创建 `android/app/src/main/res/xml/file_paths.xml`:
|
||
|
||
```xml
|
||
<?xml version="1.0" encoding="utf-8"?>
|
||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||
<!-- External storage -->
|
||
<external-path name="external_files" path="." />
|
||
<!-- Internal app storage -->
|
||
<files-path name="files" path="." />
|
||
<!-- Cache directory -->
|
||
<cache-path name="cache" path="." />
|
||
<!-- External cache -->
|
||
<external-cache-path name="external_cache" path="." />
|
||
<!-- Downloads directory -->
|
||
<external-path name="downloads" path="Download/" />
|
||
<!-- External app-specific files directory (Android/data/包名/files/) -->
|
||
<!-- 用于权限被拒绝时,使用应用私有目录存储下载的 APK -->
|
||
<external-files-path name="external_app_files" path="." />
|
||
</paths>
|
||
```
|
||
|
||
## 📡 服务端返回协议
|
||
|
||
服务端需要返回包含以下字段的 JSON:
|
||
|
||
```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"]
|
||
}
|
||
```
|
||
|
||
### 关键字段说明
|
||
|
||
- **versionBuildNumber**(必填):版本号(整数),用于比较。如果大于当前版本号,则提示更新。
|
||
- **versionName**(必填):版本名称,如 "1.0.1"。如果 BuildNumber 相同但 VersionName 更大(字典序),也会提示更新。
|
||
- **appMarkets**(可选):Android 应用市场白名单。配置后,优先尝试跳转已安装且在白名单中的市场。
|
||
- **supportedMethods**(可选):指定支持的更新方式(market/browser/inApp)。
|
||
|
||
## 🔧 进阶能力
|
||
|
||
### 1) 网络配置
|
||
|
||
支持开发/生产环境切换,以及自定义 HTTP 配置(如 Headers、超时):
|
||
|
||
```dart
|
||
// 自动选择(Debug 绕过证书、Release 严格校验)
|
||
AppUpgradePlugin().configureHttp(HttpConfig.auto);
|
||
|
||
// 手动配置:
|
||
AppUpgradePlugin().configureHttp(const HttpConfig(
|
||
ignoreCertificate: false,
|
||
enableLog: true,
|
||
connectTimeout: 30,
|
||
headers: {'Authorization': 'Bearer xxx'},
|
||
));
|
||
```
|
||
|
||
### 2) 权限助手(Android)
|
||
|
||
```dart
|
||
import 'package:yx_app_upgrade_flutter/core/permission_helper.dart';
|
||
|
||
// 检查并请求存储权限
|
||
final hasStorage = await PermissionHelper.checkAndRequestStoragePermission(context: context);
|
||
|
||
// 检查并请求安装权限
|
||
final hasInstall = await PermissionHelper.checkAndRequestInstallPermission(context: context);
|
||
```
|
||
|
||
### 3) 预下载 APK
|
||
|
||
```dart
|
||
// 后台预下载 APK(不显示 UI)
|
||
final apkPath = await AppUpgradeSimple.instance.preDownloadApk(
|
||
url: 'https://your-cdn.com/app-release.apk',
|
||
onProgress: (progress) {
|
||
print('下载进度: ${progress.percentage}%');
|
||
},
|
||
);
|
||
```
|
||
|
||
## 🤝 贡献
|
||
|
||
欢迎提交 Issue 与 Pull Request!
|
||
|
||
## 📄 许可证
|
||
|
||
MIT License
|