Flutter中App升级实现

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 样式

故障排除

常见问题

  1. 升级检查不工作

    • 检查网络连接
    • 验证 API 认证信息
    • 确认后端 API 返回正确的 XML 格式
  2. 对话框样式异常

    • 确认平台检测正确
    • 检查主题配置
  3. 语言显示错误

    • 验证 AppLocalizations 配置
    • 确认支持的语言列表

调试技巧

scss 复制代码
// 启用调试日志
Upgrader.clearSavedSettings();// 清除缓存设置
debugPrint('Platform: $platformString');
debugPrint('AppcastURL: $appcastURL');

总结

upgrader 插件为应用提供了完整的版本更新解决方案,通过合理的配置和集成,可以实现:

  • 自动版本检查
  • 优雅的用户提示
  • 强制更新支持
  • 多平台适配
  • 国际化支持

正确使用该插件可以显著提升用户体验和应用的维护效率。

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax