|
|
||
|---|---|---|
| android | ||
| example | ||
| ios | ||
| lib | ||
| test | ||
| .gitignore | ||
| .metadata | ||
| CHANGELOG.md | ||
| LICENSE | ||
| README.md | ||
| USAGE_GUIDE.md | ||
| analysis_options.yaml | ||
| devtools_options.yaml | ||
| pubspec.yaml | ||
README.md
App Upgrade Plugin
一款功能强大且灵活的 Flutter 应用内更新插件,专为提供符合主流平台用户习惯的无缝升级体验而设计。插件提供了简化版和增强版两套 API,满足不同复杂度的使用需求。
✨ 核心特性
- 🎯 智能平台适配:Android 支持完整的下载-安装流程,iOS 自动跳转 App Store
- 🔄 双模式更新:非强制更新(后台下载)+ 强制更新(阻塞式对话框)
- 🛡️ 全面权限管理:自动适配不同 Android 版本的存储、安装、通知权限
- 📱 现代化 UI:Material Design 风格对话框,支持暗色主题和自定义样式
- 🌐 健壮网络层:基于 Dio,支持断点续传、重试机制、证书配置
- 🔒 安全可靠:MD5/SHA256 文件校验,防止下载文件损坏
- 🎨 高度可定制:丰富的配置选项和回调接口
📦 安装
在 pubspec.yaml 中添加依赖:
dependencies:
app_upgrade_plugin: ^1.0.0
🚀 快速开始
方式一:简化版 API(推荐新手)
import 'package:app_upgrade_plugin/app_upgrade_plugin.dart';
// 一行代码实现完整升级流程
void checkUpdate(BuildContext context) {
AppUpgradeSimple.instance.checkUpdate(
context: context,
url: 'https://your-api.com/check-update',
params: {'channel': 'release'}, // 可选参数
showNoUpdateToast: true,
autoDownload: true,
autoInstall: false,
);
}
方式二:分离式 API(更灵活)
// 1. 检查更新(纯逻辑,不涉及UI)
final upgradeInfo = await AppUpgradeSimple.instance.checkUpdateSilent(
url: 'https://your-api.com/check-update',
params: {'platform': 'android'},
);
// 2. 根据需要显示UI
if (upgradeInfo != null && context.mounted) {
AppUpgradeSimple.instance.showUpgradeDialog(
context: context,
info: upgradeInfo,
autoDownload: true,
autoInstall: false,
);
}
方式三:增强版 API(高级用户)
final plugin = AppUpgradePluginEnhanced.instance;
// 配置插件
plugin.configure(
debugMode: true,
wifiOnly: false,
autoCheck: true,
);
// 添加下载监听
plugin.addDownloadCallback((task) {
print('下载进度: ${task.progress}%');
});
// 智能检查更新
final info = await plugin.checkUpdateSmart(
'https://your-api.com/check-update'
);
🎨 UI 展示
插件提供多种精美的 UI 组件:
- 版本更新对话框:显示版本信息、更新内容、文件大小
- 下载进度对话框:实时显示下载进度和状态
- 应用市场选择:支持多应用商店选择(华为、小米、OPPO等)
- 权限申请对话框:友好的权限说明和引导
⚙️ Android 配置
1. 权限配置
在 android/app/src/main/AndroidManifest.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"/>
<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>
</manifest>
2. FileProvider 路径配置
创建 android/app/src/main/res/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 外部存储 -->
<external-path name="external_files" path="." />
<!-- 应用内部存储 -->
<files-path name="files" path="." />
<!-- 缓存目录 -->
<cache-path name="cache" path="." />
<!-- 外部缓存 -->
<external-cache-path name="external_cache" path="." />
<!-- 下载目录 -->
<external-path name="downloads" path="Download/" />
</paths>
3. Gradle 配置(可选)
在 android/app/build.gradle 中:
android {
compileSdk 34
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
}
📡 服务端 API 协议
你的版本检查接口需要返回以下格式的 JSON:
{
"hasUpdate": true,
"isForceUpdate": false,
"versionBuildNumber": "101",
"versionName": "1.0.1",
"updateContent": "1. 修复了登录问题\n2. 优化了界面显示\n3. 提升了性能",
"downloadUrl": "https://your-cdn.com/app-release.apk",
"appStoreUrl": "https://apps.apple.com/app/id123456789",
"apkSize": 25165824,
"apkMd5": "d41d8cd98f00b204e9800998ecf8427e",
"appMarkets": [
{
"name": "华为应用市场",
"packageName": "com.huawei.appmarket",
"url": "appmarket://details?id=com.yourapp.package"
},
{
"name": "小米应用商店",
"packageName": "com.xiaomi.market",
"url": "mimarket://details?id=com.yourapp.package"
}
]
}
字段说明
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
hasUpdate |
boolean | ✅ | 是否有更新 |
isForceUpdate |
boolean | ✅ | 是否强制更新 |
versionCode |
string | ✅ | 版本号(数字字符串,用于版本比较) |
versionName |
string | ✅ | 版本名称(显示给用户) |
updateContent |
string | ✅ | 更新内容描述 |
downloadUrl |
string | Android必需 | APK下载地址 |
appStoreUrl |
string | iOS必需 | App Store链接 |
apkSize |
number | ❌ | APK文件大小(字节) |
apkMd5 |
string | ❌ | APK文件MD5校验值 |
appMarkets |
array | ❌ | 应用市场列表 |
🔧 高级配置
网络配置
// 自动模式(推荐)
// Debug: 自动绕过证书验证
// Release: 严格证书验证
// 手动配置
AppUpgradePlugin().configureHttp(HttpConfig(
ignoreCertificate: false, // 是否忽略证书
enableLog: true, // 启用网络日志
connectTimeout: 30, // 连接超时(秒)
receiveTimeout: 60, // 接收超时(秒)
defaultMethod: 'GET', // 默认请求方法
headers: { // 自定义请求头
'User-Agent': 'MyApp/1.0',
},
));
权限管理
插件提供了独立的权限管理工具:
import 'package:app_upgrade_plugin/core/permission_helper.dart';
// 检查并请求存储权限
final hasStorage = await PermissionHelper.checkAndRequestStoragePermission(
context: context,
);
// 检查并请求安装权限
final hasInstall = await PermissionHelper.checkAndRequestInstallPermission(
context: context,
);
// 检查并请求通知权限
final hasNotification = await PermissionHelper.checkAndRequestNotificationPermission(
context: context,
);
// 直接打开安装权限设置页面(新功能)
final opened = await AppUpgradePlugin().openInstallPermissionSettings();
if (opened) {
print('成功打开安装权限设置页面');
} else {
print('无法打开设置页面(非Android设备或系统限制)');
}
精确权限设置跳转
相比传统的 openAppSettings() 方法会打开应用的全部设置页面,新增的 openInstallPermissionSettings() 方法可以更精确地定位到安装权限设置:
- Android 8.0+:直接跳转到当前应用的"安装未知应用"权限页面
- Android 8.0-:跳转到应用详情页面
- 厂商适配:针对小米、华为、OPPO、Vivo、三星等定制ROM优化
- 多重降级:确保在各种情况下都能成功跳转到相关设置页面
// 方法1:使用系统流程安装(推荐,类似主流应用)
final systemSuccess = await AppUpgradePlugin().installApkWithSystemFlow(apkPath);
if (systemSuccess) {
print('使用系统流程启动安装');
} else {
print('系统流程安装失败');
}
// 方法2:传统安装方式(需要预先检查权限)
final traditionalSuccess = await AppUpgradePlugin().installApk(apkPath);
// 如果需要手动管理权限,可以使用精确跳转
final settingsSuccess = await AppUpgradePlugin().openInstallPermissionSettings();
// 获取设备信息用于调试
final deviceInfo = await AppUpgradePlugin().getDeviceInfo();
print('设备制造商: ${deviceInfo?['manufacturer']}');
print('Android版本: ${deviceInfo?['release']}');
厂商特殊适配:
| 厂商 | 特殊处理 | 预期效果 |
|---|---|---|
| 小米/红米 | MIUI权限管理页面 | 直接跳转到应用权限设置 |
| 华为/荣耀 | EMUI/HarmonyOS适配 | 跳转到应用管理页面 |
| OPPO | ColorOS标准方式 | 直接跳转到安装权限 |
| Vivo | FunTouch OS标准方式 | 直接跳转到安装权限 |
| 三星 | One UI标准方式 | 直接跳转到安装权限 |
| 原生Android | 标准Intent | 直接跳转到安装权限 |
两种安装方式对比
| 方法 | 权限检查 | 用户体验 | 适用场景 |
|---|---|---|---|
installApk() |
预先检查权限,无权限时返回错误 | 需要开发者处理权限申请 | 需要完全控制安装流程 |
installApkWithSystemFlow() |
让系统处理权限检查 | 类似主流应用,直接弹出安装确认 | 推荐使用,体验更好 |
installApkWithSystemFlow() 的优势:
- ✅ 类似盒马、美团等主流应用的安装体验
- ✅ 系统自动处理权限检查和用户确认
- ✅ 无需开发者手动管理"安装未知应用"权限
- ✅ 弹出"XX正尝试安装应用"对话框,用户点击"继续"即可
// 推荐的安装流程
Future<void> installUpdate(String apkPath) async {
final success = await AppUpgradePlugin().installApkWithSystemFlow(apkPath);
if (success) {
print('安装程序已启动,等待用户确认');
} else {
print('启动安装程序失败');
}
}
动态配置安装策略
插件提供了灵活的配置系统,可以根据需要选择不同的安装策略:
import 'package:app_upgrade_plugin/app_upgrade_plugin.dart';
// 方式1:使用预定义配置
await AppUpgradePlugin().installApkWithConfig(apkPath, config: InstallConfig.systemFlow);
await AppUpgradePlugin().installApkWithConfig(apkPath, config: InstallConfig.preCheckPermission);
await AppUpgradePlugin().installApkWithConfig(apkPath, config: InstallConfig.smart);
// 方式2:自定义配置
final customConfig = InstallConfig(
strategy: InstallStrategy.smart,
autoOpenSettings: true,
showPermissionRationale: true,
rationaleTitle: '需要安装权限',
rationaleContent: '为了完成应用更新,需要允许安装未知来源的应用。',
);
await AppUpgradePlugin().installApkWithConfig(apkPath, config: customConfig);
// 方式3:根据用户设置动态选择
InstallStrategy getUserPreferredStrategy() {
// 从用户设置或配置文件读取
final userPreference = getSettingsFromStorage();
switch (userPreference) {
case 'system': return InstallStrategy.systemFlow;
case 'permission': return InstallStrategy.preCheckPermission;
case 'smart': return InstallStrategy.smart;
default: return InstallStrategy.systemFlow;
}
}
final strategy = getUserPreferredStrategy();
final config = InstallConfig(strategy: strategy, autoOpenSettings: true);
await AppUpgradePlugin().installApkWithConfig(apkPath, config: config);
三种策略对比:
| 策略 | 行为 | 适用场景 |
|---|---|---|
systemFlow |
让系统处理所有权限检查 | 希望类似主流应用的体验 |
preCheckPermission |
预先检查权限,无权限时跳转设置 | 需要完全控制权限流程 |
smart |
有权限用预检查,无权限用系统流程 | 平衡控制和体验 |
🐛 故障排除
常见问题
Q: 安装失败,提示 "解析包时出现问题"
A: 检查以下几点:
- APK 文件是否完整下载(检查文件大小)
- APK 签名是否正确
- 设备架构是否匹配(armeabi-v7a, arm64-v8a)
Q: 权限申请失败
A: 确保:
- AndroidManifest.xml 中已声明相应权限
- FileProvider 配置正确
- 在 MaterialApp 环境中调用权限申请
Q: 下载失败或进度不更新
A: 检查:
- 网络连接是否正常
- 下载URL是否可访问
- 服务器是否支持断点续传
Q: iOS 不跳转 App Store
A: 确认:
appStoreUrl字段格式正确- URL 为有效的 App Store 链接
调试技巧
开启调试模式以获取详细日志:
// 简化版
AppUpgradeSimple.instance.init(debugMode: true);
// 增强版
AppUpgradePluginEnhanced.instance.configure(debugMode: true);
📚 API 文档
AppUpgradeSimple
| 方法 | 描述 |
|---|---|
checkUpdate() |
检查更新并显示UI |
checkUpdateSilent() |
静默检查更新 |
showUpgradeDialog() |
显示升级对话框 |
AppUpgradePluginEnhanced
| 方法 | 描述 |
|---|---|
configure() |
配置插件 |
checkUpdateSmart() |
智能检查更新 |
downloadApkSmart() |
智能下载APK |
installApkSmart() |
智能安装APK |
addDownloadCallback() |
添加下载监听 |
PermissionHelper
| 方法 | 描述 |
|---|---|
checkAndRequestStoragePermission() |
存储权限 |
checkAndRequestInstallPermission() |
安装权限 |
checkAndRequestNotificationPermission() |
通知权限 |
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
MIT License