Flutter Chen Updater

一个功能强大的Flutter应用内更新插件,支持Android APK自动下载、安装和iOS跳转App Store。

✨ 特性

  • 跨平台支持: Android APK自动更新,iOS跳转App Store
  • 智能下载: 支持断点续传、文件校验、多重备用方案
  • 权限管理: 自动处理Android安装权限、存储权限
  • 强制更新: 支持可选更新和强制更新模式
  • 进度监控: 实时下载进度回调
  • 文件校验: MD5文件完整性验证
  • 生命周期管理: 智能处理应用前后台切换
  • 自定义UI: 支持自定义更新对话框

效果预览

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

📦 安装

在你的 pubspec.yaml 文件中添加依赖:

dependencies:flutter_chen_updater: ^1.0.0

然后运行:

flutter pub get

⚙️ 权限配置

Android

android/app/src/main/AndroidManifest.xml 中添加必要权限:

<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" /><!-- 存储权限 (Android 9及以下) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" /><!-- 安装权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /><!-- 网络状态权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

🚀 基础用法

1. 简单更新检查

import 'package:flutter_chen_updater/flutter_chen_updater.dart';void checkForUpdate() {final updateInfo = UpdateInfo(version: '1.1.0',downloadUrl: 'https://example.com/app-v1.1.0.apk',iosUrl: 'https://apps.apple.com/app/id123456789',description: '1. 修复已知问题\n2. 优化用户体验\n3. 新增功能特性',isForceUpdate: false,);Updater.checkAndUpdate(context,updateInfo,onAlreadyLatest: () => print('已是最新版本'),onConfirm: () => print('用户确认更新'),onCancel: () => print('用户取消更新'),);
}

2. 带进度监控的更新

void checkForUpdateWithProgress() {final updateInfo = UpdateInfo(version: '1.1.0',downloadUrl: 'https://example.com/app-v1.1.0.apk',description: '更新说明',fileHash: 'abc123def456', // 可选:文件MD5校验hashAlgorithm: 'md5',fileSize: 15 * 1024 * 1024, // 15MB);Updater.checkAndUpdate(context,updateInfo,onProgress: (progress) {print('下载进度: ${(progress.progress * 100).toStringAsFixed(1)}%');print('已下载: ${progress.downloaded} / ${progress.total}');},onConfirm: () => print('开始下载更新'),);
}

3. 强制更新示例

void forceUpdate() {final updateInfo = UpdateInfo(version: '2.1.0',description: '重要安全更新,请立即升级',downloadUrl: 'https://example.com/app-v2.1.0.apk',isForceUpdate: true, // 强制更新,用户无法取消);Updater.checkAndUpdate(context, updateInfo);
}

4. 自定义对话框

4.1 使用 dialogBuilder 自定义
Future<bool> customDialog(BuildContext context, UpdateInfo updateInfo) {return showDialog<bool>(context: context,barrierDismissible: !updateInfo.isForceUpdate,builder: (context) => AlertDialog(title: Text('发现新版本 ${updateInfo.version}'),content: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Text(updateInfo.description),if (updateInfo.fileSize != null)Padding(padding: const EdgeInsets.only(top: 8.0),child: Text('大小: ${(updateInfo.fileSize! / 1024 / 1024).toStringAsFixed(1)}MB'),),],),actions: [if (!updateInfo.isForceUpdate)TextButton(onPressed: () => Navigator.pop(context, false),child: const Text('稍后更新'),),ElevatedButton(onPressed: () => Navigator.pop(context, true),child: const Text('立即更新'),),],),) ?? false;
}void checkWithCustomDialog() {final updateInfo = UpdateInfo(version: '1.1.0',downloadUrl: 'https://example.com/app.apk',description: '重要更新说明',);Updater.checkAndUpdate(context,updateInfo,dialogBuilder: customDialog,);
}
4.2 使用 UpdateDialog 灵活配置
void checkWithFlexibleDialog() {final updateInfo = UpdateInfo(version: '1.2.0',downloadUrl: 'https://example.com/app.apk',description: '• 修复重要安全漏洞\n• 优化启动速度\n• 新增夜间模式',fileSize: 25 * 1024 * 1024, // 25MB);showDialog<bool>(context: context,barrierDismissible: !updateInfo.isForceUpdate,builder: (context) => UpdateDialog(updateInfo: updateInfo,// 自定义标题title: Container(padding: const EdgeInsets.all(16),decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.blue, Colors.purple],),),child: Row(children: [Icon(Icons.system_update, color: Colors.white),const SizedBox(width: 8),Text('重要更新 V${updateInfo.version}',style: const TextStyle(color: Colors.white,fontWeight: FontWeight.bold,),),],),),// 自定义内容content: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Container(padding: const EdgeInsets.all(16),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Text('更新内容',style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold,),),const SizedBox(height: 8),Text(updateInfo.description),const SizedBox(height: 12),if (updateInfo.fileSize != null)Container(padding: const EdgeInsets.symmetric(horizontal: 12,vertical: 6,),decoration: BoxDecoration(color: Colors.grey.shade100,borderRadius: BorderRadius.circular(16),),child: Text('安装包大小: ${(updateInfo.fileSize! / 1024 / 1024).toStringAsFixed(1)}MB',style: Theme.of(context).textTheme.bodySmall,),),],),),],),// 自定义底部操作栏footer: Container(padding: const EdgeInsets.all(16),child: Row(children: [if (!updateInfo.isForceUpdate) ...[Expanded(child: OutlinedButton(onPressed: () => Navigator.pop(context, false),child: const Text('稍后提醒'),),),const SizedBox(width: 12),],Expanded(flex: updateInfo.isForceUpdate ? 1 : 1,child: ElevatedButton.icon(onPressed: () => Navigator.pop(context, true),icon: const Icon(Icons.download),label: const Text('立即更新'),),),],),),),);
}

5. 纯下载功能

void downloadOnly() {final updateInfo = UpdateInfo(version: '1.1.0',downloadUrl: 'https://example.com/app.apk',description: '更新包',);Updater.download(updateInfo).listen((progress) {if (progress.isCompleted && progress.filePath != null) {print('下载完成: ${progress.filePath}');// 稍后安装Updater.installApk(progress.filePath!,onSuccess: () => print('安装成功'),onError: (error) => print('安装失败: $error'),);} else if (progress.isFailed) {print('下载失败: ${progress.error}');}});
}

6. 版本比较

void checkVersionUpdate() {final currentVersion = '1.0.0';final newVersion = '1.1.0';final needUpdate = Updater.needUpdate(currentVersion, newVersion);print('是否需要更新: $needUpdate');
}

📚 API 文档

UpdateInfo 类

更新信息配置类:

class UpdateInfo {final String version;           // 新版本号 (必需)final String? downloadUrl;      // Android APK下载链接final String? iosUrl;          // iOS App Store链接final String description;       // 更新说明 (必需)final bool isForceUpdate;      // 是否强制更新final String? fileHash;        // 文件哈希值 (可选)final String? hashAlgorithm;   // 哈希算法 (默认: 'md5')final int? fileSize;           // 文件大小 (字节)final Map<String, dynamic>? extra; // 额外数据
}

Updater 类

主要更新器类:

静态方法
  • checkAndUpdate() - 检查并更新应用
  • download() - 纯下载方法(不自动安装)
  • installApk() - 安装APK文件
  • needUpdate() - 版本比较
  • cancelDownload() - 取消下载
  • dispose() - 清理资源

DownloadProgress 类

下载进度信息:

class DownloadProgress {final int downloaded;          // 已下载字节数final int total;              // 总字节数final double progress;        // 进度 (0.0 - 1.0)final DownloadStatus status;  // 下载状态final String? error;          // 错误信息final String? filePath;       // 文件路径
}

DownloadStatus 枚举

enum DownloadStatus {idle,         // 空闲downloading,  // 下载中paused,       // 暂停completed,    // 完成failed,       // 失败cancelled,    // 取消installing    // 安装中
}

🔧 高级功能

文件校验

插件支持MD5文件完整性校验:

final updateInfo = UpdateInfo(version: '1.1.0',downloadUrl: 'https://example.com/app.apk',description: '安全更新',fileHash: 'a1b2c3d4e5f6...',hashAlgorithm: 'md5',
);

权限处理

插件自动处理以下权限:

  1. 存储权限 (Android 9及以下)
  2. 安装权限 (Android 8+)
  3. 网络权限

对于缺失权限,插件会:

  • 自动请求权限
  • 引导用户到系统设置页面
  • 监听应用生命周期自动重试

生命周期管理

插件智能处理应用前后台切换:

  • 用户跳转权限设置后返回应用时自动重试安装
  • 后台下载任务保持活跃
  • 应用退出时自动清理资源

💡 错误处理

插件提供完善的错误处理机制:

Updater.checkAndUpdate(context,updateInfo,onProgress: (progress) {if (progress.isFailed) {// 处理下载失败showDialog(context: context,builder: (_) => AlertDialog(title: const Text('下载失败'),content: Text(progress.error ?? '未知错误'),actions: [TextButton(onPressed: () => Navigator.pop(context),child: const Text('确定'),),],),);}},
);

🚦 最佳实践

  1. 版本检查: 建议在应用启动时检查更新
  2. 网络判断: 在检查更新前判断网络状态
  3. 用户体验: 避免在关键操作时弹出更新提示
  4. 资源清理: 应用退出时调用 Updater.dispose()
  5. 错误日志: 记录更新过程中的错误信息用于调试

❓ 常见问题

Q: Android安装失败怎么办?

A: 检查是否授予了"安装未知应用"权限,插件会自动引导用户设置。

Q: 下载速度慢怎么办?

A: 插件使用Android系统下载管理器和HTTP备用方案,确保最佳下载体验。

Q: 如何支持增量更新?

A: 当前版本不支持增量更新,建议使用文件校验确保完整性。

Q: iOS如何实现自动更新?

A: iOS由于系统限制只能跳转App Store,无法实现APK式的自动更新。

⚠️ 注意事项

  1. Android权限

    • Android 6.0+ 需要运行时申请存储权限
    • Android 8.0+ 需要安装未知来源应用权限
    • Android 10+ 使用作用域存储,无需存储权限
  2. 文件安全

    • 建议使用HTTPS下载链接
    • 强烈推荐设置fileHash进行文件完整性校验
    • 下载的APK文件会自动进行基础验证
  3. 用户体验

    • 避免在用户进行重要操作时弹出更新提示
    • 强制更新应谨慎使用,仅在安全更新时使用
    • 提供清晰的更新说明和文件大小信息

📄 许可证

MIT License

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/920779.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920779.shtml
英文地址,请注明出处:http://en.pswp.cn/news/920779.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker 1分钟 快速搭建 redis 哨兵集群

使用 docker-compose 1 分钟搭建好 1主2从3哨兵的 redis 哨兵集群 目录结构 redis-sentinel-cluster ├── check_redis.sh ├── docker-compose.yml ├── redis │ └── redis.conf ├── sentinel │ └── sentinel.confdocker-compose.yml 配置 version: 3…

Git与DevOps实战:从版本控制到自动化部署

一、版本控制1.什么是版本控制&#xff1f;版本控制用于高效追踪和管理项目开发中的代码、配置及文档变更历史&#xff0c;确保团队成员始终使用正确版本&#xff0c;并支持版本回溯、差异比较和文件恢复。它能带来以下优势&#xff1a;通过历史记录保障数据安全与完整性&#…

大模型——利用RAG构建智能问答平台实战

利用RAG构建智能问答平台实战 目前公司的智能问答平台利用RAG技术构建,现给大家分享下通RAG技术构建智能问平台的具体流程和原理。 一、什么是RAG RAG是检索增强生成技术(Retrieval-Augmented Generation),目前是构建智能问答的重要技术。RAG相比传统的检索可以可以减少…

flume事务机制详解:保障数据可靠性的核心逻辑

flume事务机制详解&#xff1a;保障数据可靠性的核心逻辑 在数据采集过程中&#xff0c;“不丢数据、不重数据” 是核心需求。Flume 之所以能在分布式环境下保证数据可靠性&#xff0c;关键在于其内置的事务机制。Flume 通过在 “Source → Channel” 和 “Channel → Sink” …

第四十九天(springboot模版注入ThymeleafFreemarkerVelocity)

开发框架-SpringBoot 参考&#xff1a;Spring Boot 中文文档 新建一个spring Boot 项目&#xff0c;修改服务器url为 aliyun.com 不然没有与jdk8版本对应的java 选择一个spring web 库&#xff0c;点击创建即可 来到这个页面点击运行 启动的是8080端口&#xff0c;用127.0.0.1…

Spring MVC 九大组件源码深度剖析(六):HandlerExceptionResolver - 异常处理的艺术

文章目录一、异常处理的核心价值二、核心接口设计三、四大内置实现类源码解析1. ExceptionHandlerExceptionResolver&#xff08;现代异常处理核心&#xff09;2. ResponseStatusExceptionResolver&#xff08;HTTP状态码处理&#xff09;3. DefaultHandlerExceptionResolver&a…

MCP(Model Context Protocol,模型上下文协议)介绍

1. 背景 随着大语言模型&#xff08;LLM, Large Language Model&#xff09;的应用越来越广泛&#xff0c;一个核心问题逐渐凸显&#xff1a; 模型在对话或推理时&#xff0c;往往只能依赖有限上下文窗口。外部工具、知识库、应用接口如何统一接入模型&#xff0c;缺乏标准协议…

synchronized的锁对象 和 wait,notify的调用者之间的关系

谁调用了wait和notify方法&#xff0c;会决定这两个方法的控制范围吗&#xff1f;你的问题非常深入&#xff0c;涉及到 wait() 和 notify() 方法的控制范围和作用域。让我们详细分析一下&#xff1a;✅ 核心概念&#xff1a;控制范围由“锁对象”决定wait() 和 notify() 的控制…

【技术教程】如何将文档编辑器集成到用 .Net 编写的网络应用程序中

在现代网络应用中&#xff0c;​富文本编辑能力已成为内容管理系统的核心需求。对于 .NET 开发者而言&#xff0c;选择适合的编辑器并高效集成&#xff0c;是构建企业级应用的关键一步&#xff0c;可让项目管理、 CRM 或定制化系统具备原生办公能力&#xff0c;消除频繁切换应用…

【大模型记忆-Mem0详解-1】概述

目的和能力 Mem0 通过提供以下功能将无状态 AI 应用程序转换为有状态、支持内存的系统&#xff1a; 持久记忆 &#xff1a;跨会话长期保留用户偏好、对话历史记录和上下文信息多级内存 &#xff1a;支持具有自适应个性化的用户级、会话级和代理级内存智能提取 &#xff1a;基于…

2024年山东省信息学小学组(CSP-X)第一轮题解

2024年山东省信息学小学组(CSP-X)第一轮题解 原题下载 单项选择题 阅读程序 阅读程序 #1 判断题 阅读程序 #2 判断题 单选题 阅读程序 #3 判断题 单选题 完善程序 消灭怪兽 位运算操作 原题下载 CSP-X2024小学组(山东)第一轮试题以及答案 单项选择题 共 15 题,每题 2 分…

SW - 用装配图的方式组合多个子零件然后转换成为零件,可维护性好

文章目录SW - 用装配图的方式组合多个子零件然后转换成为零件&#xff0c;可维护性好概述笔记例子将装配图另存为零件将零件图中的多个实体组合为一个实体的特征备注ENDSW - 用装配图的方式组合多个子零件然后转换成为零件&#xff0c;可维护性好 概述 以前画机械零件&#x…

PhotoshopImageGenerator:基于Photoshop的自动化图像数据集生成工具

整体逻辑与设计思路 PhotoshopImageGenerator是一个基于Python和Win32COM的自动化工具,通过控制Adobe Photoshop CC 2019创建多样化的图像数据集。其核心设计思路是通过程序化调用Photoshop的图像编辑能力,为基础图像添加随机元素(图片、文本、形状)和效果,快速生成大量变…

macos自动安装emsdk4.0.13脚本

1.替换文件 emsdk #!/bin/sh # Copyright 2019 The Emscripten Authors. All rights reserved. # Emscripten is available under two separate licenses, the MIT license and the # University of Illinois/NCSA Open Source License. Both these licenses can be # foun…

c++ Effective c++ 条款5

class MyClass { public:MyClass(int& ref, const int c_val) : myRef(ref), myConstVal(c_val) {}// 明确删除拷贝操作MyClass(const MyClass&) delete;MyClass& operator(const MyClass&) delete;private:int& myRef; // 引用成员const int myCo…

如何使用 Xshell 8 连接到一台 CentOS 7 电脑(服务器)

什么是 Xshell&#xff1f; Xshell 是一款功能强大的、适用于 Windows 平台的终端模拟器。它支持 SSH (Secure Shell)、SFTP、TELNET、RLOGIN 和 SERIAL 等多种网络协议&#xff0c;让用户能够安全地连接和管理远程服务器。 对于开发者、系统管理员和网络工程师来说&#xff…

CSS scale函数详解

目录 基本语法 核心特性 常用场景示例 1. 等比例缩放&#xff08;X 轴和 Y 轴相同&#xff09; 2. 非等比例缩放&#xff08;X 轴和 Y 轴不同&#xff09; 3. 翻转并缩放 4. 配合过渡动画实现交互效果 5. 图片悬停缩放效果 6. 缩放原点调整 与其他变换组合使用 注意…

【MATLAB代码】基于EKF的二维组合导航仿真代码,状态量为位置、速度、航向角与IMU偏置,观测量为XY轴的位置和速度,附完整代码

8维状态量(2维位置、2维速度、航向角、航向角偏置、2维加速度计偏置)+4维观测量(2维位置、2维速度)。 订阅专栏后,可直接查看源代码,粘贴到MATLAB空脚本中即可直接运行、得到结果 文章目录 运行结果 MATLAB源代码 程序详解 📘 程序概述 状态预测(状态转移函数) 状态雅…

OpenCV 图像轮廓检测

目录 一、轮廓检测基础概念 二、核心 API 详解&#xff1a;cv2.findContours () 参数说明&#xff1a; 返回值说明&#xff1a; 三、轮廓检测实战步骤 1. 图像预处理&#xff08;灰度化与二值化&#xff09; 2. 查找轮廓 3. 绘制轮廓 四、轮廓的常用属性与操作 1. 轮…

【图论】 Graph.jl 概览

文章目录安装基础使用基本操作全局图的指标顶点性质边性质读写图按照 .lgz 格式存储图数据&#xff08;压缩格式&#xff09;按照 .lg 格式存储图数据&#xff08;非压缩格式&#xff09;图的绘制TikzGraphs.jl Latex 论文风格GraphPlot.jl 通常与 Compose.jl 一起使用SGtSNEpi…