Flutter自动更新插件flutter_autoupdate的使用
Flutter自动更新插件flutter_autoupdate的使用
本库允许你在Android、iOS和Windows的Flutter应用中轻松添加自动更新功能。
我们的使用场景是在iOS上启动App Store,在Android或Windows上安装/执行APK或Windows可执行文件;因此,此包应运而生。要使用此包,你应该遵循以下版本模板格式。
特性
- 从iTunes App Store/远程URL获取更新
- 启动App Store
- 带有进度的下载功能
- 下载时进行SHA512哈希校验
安装
在你的Android应用中添加以下内容:
AndroidManifest.xml
<!-- Provider -->
<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>
android/app/src/main/res/xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/<package name>/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>
将<package name>
替换为你的应用包名。
示例
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_autoupdate/flutter_autoupdate.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:version/version.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
initPlatformState();
}
UpdateResult? _result;
DownloadProgress? _download;
var _startTime = DateTime.now().millisecondsSinceEpoch;
var _bytesPerSec = 0;
// 平台消息是异步的,所以我们通过异步方法初始化。
Future<void> initPlatformState() async {
UpdateResult? result;
// 如果小部件在异步平台消息传输期间被树移除,则我们希望丢弃回复而不是调用setState来更新我们的不存在的外观。
if (!mounted) return;
if (Platform.isAndroid || Platform.isIOS) {
var status = await Permission.storage.status;
if (status.isDenied) {
await Permission.storage.request();
}
}
String versionUrl;
if (Platform.isAndroid) {
versionUrl =
'https://storage.googleapis.com/download-dev.feedmepos.com/version_android_sample.json';
} else if (Platform.isWindows) {
versionUrl =
'https://storage.googleapis.com/download-dev.feedmepos.com/version_windows_sample.json';
}
/// Android/Windows
var manager = UpdateManager(versionUrl: versionUrl);
/// iOS
// var manager = UpdateManager(appId: 1500009417, countryCode: 'my');
try {
result = await manager.fetchUpdates();
setState(() {
_result = result;
});
if (Version.parse('1.0.0') < result?.latestVersion) {
var controller = await result?.initializeUpdate();
controller?.stream.listen((event) async {
setState(() {
if (DateTime.now().millisecondsSinceEpoch - _startTime >= 1000) {
_startTime = DateTime.now().millisecondsSinceEpoch;
_bytesPerSec = event.receivedBytes - _bytesPerSec;
}
_download = event;
});
if (event.completed) {
print("Downloaded completed");
await controller.close();
await result?.runUpdate(event.path, autoExit: true);
}
});
}
} on Exception catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('插件示例应用'),
),
body: Center(
child: _download != null
? Text('最新版本: ${_result!.latestVersion}\n'
'Url: ${_result!.downloadUrl}\n'
'发布说明: ${_result!.releaseNotes}\n'
'发布时间: ${_result!.releaseDate}\n\n'
'文件: ${_download!.toPrettyMB(_download!.receivedBytes)}/'
'${_download!.toPrettyMB(_download!.totalBytes)} '
'(${_download!.progress.toInt()}%)\n'
'速度: ${_download!.toPrettyMB(_bytesPerSec)}/s\n'
'目标路径: ${_download!.path}')
: null,
),
),
);
}
}
更多详细信息,请参阅示例。
版本模板
默认情况下,它会选取第一个索引作为最新版本。更多信息,可以参考sample.json。
Android
[
{
"version": "3.0.0",
"url": "https://storage.googleapis.com/download-dev.feedmepos.com/android/feedme-pos-3.0.0-beta.5.apk",
"releaseNotes": "新更新 3.0.0!",
"releaseDate": "2021-07-28T11:58:25Z",
"sha512": "2e0349c1e729eac0f4cb9f831fa1130241743c8db9e115013091dbeec6b8b86dc18c62bcbfab516033869c8ec8c8967615c622303d4bee62640c3b507051aca2"
},
{
"version": "1.4.5",
"url": "https://storage.googleapis.com/download-dev.feedmepos.com/android/feedme-pos-1.4.5.apk",
"releaseNotes": "新更新 1.4.5!",
"releaseDate": "2021-06-16T11:58:25Z",
"sha512": "f028475ad562f9f9566213774b02e0bd3ac2198899222687613937791307ec5d326cfb79ee2882273bffd6777f9c76371d6b2eed7d46e326fd687bc95e2edb2a"
}
]
Windows
[
{
"version": "2.5.0",
"url": "https://storage.googleapis.com/download-dev.feedmepos.com/feedme_sample.exe",
"releaseNotes": "新更新 2.5.0!",
"releaseDate": "2021-07-28T11:58:25Z",
"sha512": "53d4cc95ad07470b53b3f9bc010ab8c6776f2bc2f9f3115b0807ecebcc34175f530d02e549c260112ad08c2c86a8b92d7e7f11308df0406422be8ceea76a9190"
}
]
更多关于Flutter自动更新插件flutter_autoupdate的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自动更新插件flutter_autoupdate的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于如何在Flutter项目中使用flutter_autoupdate
插件来实现应用的自动更新功能,以下是一个简要的代码示例和配置步骤。请注意,实际使用中可能需要根据具体需求进行调整。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加flutter_autoupdate
依赖:
dependencies:
flutter:
sdk: flutter
flutter_autoupdate: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
2. 配置权限(Android)
如果你的应用需要访问网络来检查更新,你需要在AndroidManifest.xml
中添加必要的权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 其他配置 -->
</manifest>
3. 初始化并使用插件
在你的Flutter项目的main.dart
或其他合适的文件中,初始化并使用flutter_autoupdate
插件。以下是一个基本的示例:
import 'package:flutter/material.dart';
import 'package:flutter_autoupdate/flutter_autoupdate.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Auto Update Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
_checkForUpdates();
}
Future<void> _checkForUpdates() async {
try {
// 假设你的更新信息是从一个JSON API获取的
String updateUrl = "https://yourserver.com/update.json";
// 使用dio或其他HTTP客户端来获取更新信息
var response = await Dio().get(updateUrl);
var updateData = response.data;
// 解析更新信息(这里假设更新信息包含版本号和新APK的下载URL)
String latestVersion = updateData['latest_version'];
String apkUrl = updateData['apk_url'];
// 获取当前应用的版本号
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String currentVersion = packageInfo.version;
// 比较版本号,如果需要更新则显示更新对话框
if (compareVersion(currentVersion, latestVersion) < 0) {
showUpdateDialog(context, latestVersion, apkUrl);
}
} catch (e) {
print("Error checking for updates: $e");
}
}
// 比较版本号的辅助函数
int compareVersion(String current, String latest) {
List<String> currentParts = current.split('.');
List<String> latestParts = latest.split('.');
int length = math.max(currentParts.length, latestParts.length);
for (int i = 0; i < length; i++) {
int currentPart = i < currentParts.length ? int.parse(currentParts[i]) : 0;
int latestPart = i < latestParts.length ? int.parse(latestParts[i]) : 0;
if (currentPart > latestPart) return 1;
if (currentPart < latestPart) return -1;
}
return 0;
}
// 显示更新对话框
Future<void> showUpdateDialog(BuildContext context, String latestVersion, String apkUrl) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // 用户不能通过点击背景关闭对话框
builder: (BuildContext context) {
return AlertDialog(
title: Text('New Update Available'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('A new version of the app is available: $latestVersion'),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: () async {
// 下载并安装APK(这里需要额外的处理,因为Flutter本身不支持直接安装APK)
// 可以引导用户到浏览器下载或者使用其他插件如`open_file`来处理APK安装
await launchUrl(Uri.parse(apkUrl));
Navigator.of(context).pop();
},
child: Text('Download Update'),
),
],
),
),
);
},
);
}
}
注意:
- 上述代码中的
Dio
是一个HTTP客户端库,用于从服务器获取更新信息。你需要先添加dio
依赖:dio: ^x.y.z
。 - 由于Flutter本身不支持直接安装APK,所以下载后需要引导用户手动安装。你可以使用
url_launcher
插件来打开下载链接。 - 版本号比较的逻辑可能需要根据实际情况进行调整。
- 在生产环境中,请确保更新信息的来源是安全可靠的,以避免潜在的安全风险。
这个示例提供了一个基本的框架,你可以根据自己的需求进一步扩展和完善。