Flutter Upgrader 插件集成指南
概述
本文档详细介绍了 Peekababy 项目中使用的 upgrader 插件的集成方式和使用方法,帮助团队成员快速理解和使用该功能。
插件信息
- 插件名称 :
upgrader - 版本 :
^11.4.0 - 功能: 自动检查应用更新并提示用户升级
- 支持平台: iOS、Android
依赖配置
pubspec.yaml 配置
yaml
dependencies:
upgrader: ^11.4.0
dio: ^5.4.0# 用于网络请求xml: ^6.5.0# 用于解析 XML 响应version: ^3.0.2# 用于版本比较
核心实现
1. 自定义认证 Store
dart
// 带认证的自定义 Appcast Storeclass AuthenticatedAppcastStore extends UpgraderAppcastStore {
final Map<String, String> headers;
AuthenticatedAppcastStore({required super.appcastURL, required this.headers});
@override
Future<UpgraderVersionInfo> getVersionInfo({
required UpgraderState state,
required Version installedVersion,
required String? country,
required String? language,
}) async {
// 创建带认证的 Appcastfinal localAppcast = Appcast(
client: state.client,
clientHeaders: headers,// 设置认证头
upgraderDevice: state.upgraderDevice,
upgraderOS: state.upgraderOS,
);
return UpgraderAppcastStore(
appcastURL: appcastURL,
appcast: localAppcast,
).getVersionInfo(
state: state,
installedVersion: installedVersion,
country: country,
language: language,
);
}
}
2. 升级服务类
ini
class UpgraderService {
static Future<Upgrader> getUpgrader(BuildContext context) async {
final languageCode = AppLocalizations.of(context)!.localeName.split('_').first;
final platform = Theme.of(context).platform;
final platformString = platform == TargetPlatform.android ? 'android' : 'ios';
// 构建 API URLfinal appcastURL = '<http://pkb.xinzhiaigc.com/functions/v1/check-update?platform=$platformString>';
// 检查是否为关键更新String? minAppVersion;
try {
final dio = Dio();
dio.options.headers = {
'User-Agent': 'Flutter App Updater',
'Accept': 'application/xml, text/xml',
'Authorization': 'Bearer <your-token>',
'apikey': '<your-api-key>',
};
final response = await dio.get(appcastURL);
if (response.statusCode == 200) {
final document = XmlDocument.parse(response.data);
final enclosure = document.findAllElements('enclosure').firstOrNull;
if (enclosure != null) {
final isCritical = enclosure.getAttribute('sparkle:criticalUpdate') == 'true';
if (isCritical) {
minAppVersion = '999.0.0';// 强制更新
}
}
}
} catch (e) {
// 静默处理错误
}
return Upgrader(
minAppVersion: minAppVersion,
storeController: UpgraderStoreController(
onAndroid: () => AuthenticatedAppcastStore(
appcastURL: appcastURL,
headers: authHeaders,
),
oniOS: () => AuthenticatedAppcastStore(
appcastURL: appcastURL,
headers: authHeaders,
),
),
messages: UpgraderMessages(code: languageCode),
);
}
}
3. UI 集成
scala
class _HomeScreenState extends State<HomeScreen> {
Upgrader? _upgrader;
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_upgrader == null) {
_initUpgrader();
}
}
void _initUpgrader() async {
try {
final upgrader = await UpgraderService.getUpgrader(context);
if (mounted) {
setState(() {
_upgrader = upgrader;
});
}
} catch (e) {
// 静默处理错误
}
}
@override
Widget build(BuildContext context) {
Widget homeContent = Scaffold(/* 你的页面内容 */);
// 条件性包装升级检查if (_upgrader != null) {
return UpgradeAlert(
upgrader: _upgrader!,
showReleaseNotes: false,
dialogStyle: Theme.of(context).platform == TargetPlatform.iOS
? UpgradeDialogStyle.cupertino
: UpgradeDialogStyle.material,
child: homeContent,
);
}
return homeContent;
}
}
后端 API 规范
请求格式
sql
GET /functions/v1/check-update?platform={android|ios}
Headers:
Authorization: Bearer <token>
apikey: <api-key>
User-Agent: Flutter App Updater
Accept: application/xml, text/xml
响应格式 (Appcast XML)
xml
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="<http://www.andymatuschak.org/xml-namespaces/sparkle>">
<channel>
<title>App Updates</title>
<item>
<title>Version 1.2.3</title>
<description>Bug fixes and improvements</description>
<pubDate>Mon, 01 Jan 2024 12:00:00 +0000</pubDate>
<enclosure
url="<https://apps.apple.com/app/your-app/id123456789>"
sparkle:version="1.2.3"
sparkle:shortVersionString="1.2.3"
sparkle:criticalUpdate="false"
type="application/octet-stream" />
</item>
</channel>
</rss>
关键特性
1. 强制更新支持
- 通过
sparkle:criticalUpdate="true"标记关键更新 - 设置
minAppVersion = "999.0.0"强制用户更新
2. 多语言支持
- 自动根据应用语言设置显示对应的升级提示
- 支持的语言由
UpgraderMessages(code: languageCode)控制
3. 平台适配
- iOS: 使用 Cupertino 风格对话框
- Android: 使用 Material 风格对话框
4. 认证支持
- 自定义
AuthenticatedAppcastStore支持 API 认证 - 通过 headers 传递认证信息
最佳实践
1. 初始化时机
scss
// ✅ 正确:在 didChangeDependencies 中初始化@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_upgrader == null) {
_initUpgrader();
}
}
// ❌ 错误:在 initState 中初始化(context 依赖可能未就绪)
2. 错误处理
scss
void _initUpgrader() async {
try {
final upgrader = await UpgraderService.getUpgrader(context);
if (mounted) {// 检查 widget 是否仍然挂载
setState(() {
_upgrader = upgrader;
});
}
} catch (e) {
// 静默处理错误,不影响应用正常使用
}
}
3. 性能优化
- 升级检查异步进行,不阻塞 UI 渲染
- 使用条件渲染,只在升级器准备好后才包装 UI
- 防重复初始化:
if (_upgrader == null)
注意事项
1. 网络依赖
- 升级检查需要网络连接
- 网络异常时应用仍能正常使用
- 建议设置合理的超时时间
2. 权限要求
- iOS: 需要网络访问权限
- Android: 需要网络访问权限
3. 应用商店政策
- 确保升级链接指向官方应用商店
- 遵守各平台的更新政策
4. 测试建议
- 测试网络异常情况
- 测试强制更新流程
- 测试不同语言环境
- 测试不同平台的 UI 样式
故障排除
常见问题
-
升级检查不工作
- 检查网络连接
- 验证 API 认证信息
- 确认后端 API 返回正确的 XML 格式
-
对话框样式异常
- 确认平台检测正确
- 检查主题配置
-
语言显示错误
- 验证
AppLocalizations配置 - 确认支持的语言列表
- 验证
调试技巧
scss
// 启用调试日志
Upgrader.clearSavedSettings();// 清除缓存设置
debugPrint('Platform: $platformString');
debugPrint('AppcastURL: $appcastURL');
总结
upgrader 插件为应用提供了完整的版本更新解决方案,通过合理的配置和集成,可以实现:
- 自动版本检查
- 优雅的用户提示
- 强制更新支持
- 多平台适配
- 国际化支持
正确使用该插件可以显著提升用户体验和应用的维护效率。