Flutter应用升级插件upgrade的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter应用升级插件upgrade的使用

1. Preparation

您需要提供一个服务器,该服务器提供版本配置文件(App Version Config File)查询和下载安装文件的服务。例如,可以使用以下链接提供的升级服务器:Upgrade Server

2. Config Before Use

Android

  1. 创建 file_provider_path.xml 文件,并添加以下内容:
<?xml version="1 .0 " encoding="utf-8"?>
<paths>
    <files-path name="files" path="/" />
    <cache-path name="cache" path="/" />
    <external-path name="external" path="/" />
    <external-cache-path name="cache" path="/" />
    <external-files-path name="files" path="/" />
</paths>
  1. android/app/src/main/AndroidManifest.xml 中添加以下权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package">
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application>
        <provider
            android:authorities="${applicationId}.fileProvider"
            android:name="androidx.core.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_provider_path"/>
        </provider>
    </application>
</manifest>

MacOS

.entitlements 文件中设置以下属性:

<dict>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.files.downloads.read-write</key>
    <true/>
</dict>

3. Create Version Config File (Appcast) at Local to Mark Current App’s Version

创建一个版本配置文件(Appcast Item),例如在 AppcastItem

4. Init Plugin in Suitable Places

初始化插件:

void main() {
  UpgradeManager.instance.init(
      url: 'http://localhost:8000/appcast/latest', // 升级服务器 URL
      currentVersionPath: 'assets/version/version.json', 
  );

  runApp(const MyApp());
}

5. Download if Need and Install

如何使用?请参阅 UpgradeManager

// 下载更新
UpgradeManager.instance.download()

// 安装更新
UpgradeManager.instance.install()

示例代码

import 'package:flutter/material.dart';
import 'package:upgrade/upgrade.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  [@override](/user/override)
  void initState() {
    super.initState();
    UpgradeManager.instance.init(
      url: 'http://localhost:8000/appcast/latest',
      currentVersionPath: 'assets/version/version.json',
    );
  }

  double progress = 0;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Plugin example app'),
      ),
      body: Stack(
        children: [
          Align(
            alignment: Alignment.topLeft,
            child: CustomUpgradeView(
              builder: (context, state) =&gt; _buildAppcastItemInfo(title: "Upgrade Current Version", item: state.current),
            ),
          ),
          Align(
            alignment: Alignment.bottomLeft,
            child: CustomUpgradeView(
              builder: (context, state) =&gt; _buildAppcastItemInfo(title: "Upgrade Latest Version", item: state.latest),
            ),
          ),
          Align(
            alignment: Alignment.bottomRight,
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
              child: CustomUpgradeStatusIndicator(
                builder: (context, status) {
                  return Text(status.name);
                },
              ),
            ),
          ),
          Align(
            alignment: Alignment.topRight,
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text("Download Progress"),
                  Padding(
                    padding: const EdgeInsets.only(top: 16),
                    child: SizedBox(
                      width: 256,
                      child: LinearProgressIndicator(value: progress, minHeight: 8,),
                    ),
                  ),
                ],
              ),
            ),
          ),
          Align(
            alignment: Alignment.center,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                GestureDetector(
                  onTap: () =&gt; UpgradeManager.instance.checkForUpdates(),
                  child: const Padding(
                    padding: EdgeInsets.symmetric(vertical: 16, horizontal: 24),
                    child: Text("Check for Updates"),
                  ),
                ),
                GestureDetector(
                  onTap: () =&gt; UpgradeManager.instance.download(onReceiveProgress: (received, total, _) {
                    setState(() {
                      progress = received / total;
                    });
                  }),
                  child: const Padding(
                    padding: EdgeInsets.symmetric(vertical: 16, horizontal: 24),
                    child: Text("Download"),
                  ),
                ),
                GestureDetector(
                  onTap: () =&gt; UpgradeManager.instance.install(),
                  child: const Padding(
                    padding: EdgeInsets.symmetric(vertical: 16, horizontal: 24),
                    child: Text("Install"),
                  ),
                )
              ],
            ),
          )
        ],
      ),
    );
  }

  Widget _buildAppcastItemInfo({required String title, AppcastItem? item}) {
    if (item == null) {
      return Text("$title: null", style: const TextStyle(fontWeight: FontWeight.bold));
    }
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text("$title: ", style: const TextStyle(fontWeight: FontWeight.bold)),
        Text("releaseNotes: ${item.releaseNotes}"),
        Text("version: ${item.version.toString()}"),
        Text("displayVersionString: ${item.displayVersionString}"),
        Text("os: ${item.os}"),
        Text("minimumSystemVersion: ${item.minimumSystemVersion}"),
        Text("maximumSystemVersion: ${item.maximumSystemVersion}"),
      ],
    );
  }
}

更多关于Flutter应用升级插件upgrade的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用升级插件upgrade的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用upgrade插件来实现应用升级的示例代码。这个示例将展示如何检测新版本、下载APK文件并提示用户安装。

首先,确保你的Flutter项目中已经添加了upgrade插件。你可以在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  upgrade: ^x.x.x  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来,我们编写代码来实现应用升级功能。假设我们有一个服务器API可以返回最新版本信息和APK下载链接。

1. 创建一个升级检查函数

首先,我们创建一个函数来检查新版本并下载APK文件。

import 'package:flutter/material.dart';
import 'package:upgrade/upgrade.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;

Future<void> checkForUpdates() async {
  // 假设服务器返回的JSON格式如下:
  // {
  //   "versionCode": 2,
  //   "versionName": "1.1.0",
  //   "apkUrl": "https://example.com/app-release.apk",
  //   "releaseNotes": "This is a new update with bug fixes and improvements."
  // }

  String latestVersionUrl = 'https://example.com/latest_version.json';
  final response = await http.get(Uri.parse(latestVersionUrl));

  if (response.statusCode == 200) {
    Map<String, dynamic> latestVersionData = jsonDecode(response.body);
    int latestVersionCode = latestVersionData['versionCode'];
    String latestVersionName = latestVersionData['versionName'];
    String apkUrl = latestVersionData['apkUrl'];
    String releaseNotes = latestVersionData['releaseNotes'];

    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    int currentVersionCode = packageInfo.versionCode;

    if (latestVersionCode > currentVersionCode) {
      showUpgradeDialog(context, latestVersionName, apkUrl, releaseNotes);
    }
  } else {
    // 处理请求失败的情况
    print('Failed to fetch latest version info');
  }
}

2. 显示升级对话框并下载APK

接下来,我们编写一个函数来显示升级对话框,并在用户同意升级后下载APK文件。

Future<void> showUpgradeDialog(BuildContext context, String latestVersionName, String apkUrl, String releaseNotes) async {
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: Text('New Update Available'),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text('Version $latestVersionName is now available!'),
          SizedBox(height: 10),
          Text('Release Notes:'),
          SizedBox(height: 5),
          Text(releaseNotes, style: TextStyle(fontSize: 14)),
        ],
      ),
      actions: <Widget>[
        TextButton(
          onPressed: () => Navigator.of(context).pop(),
          child: Text('Skip'),
        ),
        TextButton(
          onPressed: () async {
            Navigator.of(context).pop();
            await downloadAndInstallApk(apkUrl);
          },
          child: Text('Update Now'),
        ),
      ],
    ),
  );
}

Future<void> downloadAndInstallApk(String apkUrl) async {
  Directory appDocDir = await getApplicationDocumentsDirectory();
  String apkFilePath = '${appDocDir.path}/app-release.apk';
  File apkFile = File(apkFilePath);

  var response = await http.get(Uri.parse(apkUrl));

  if (response.statusCode == 200) {
    await apkFile.writeAsBytes(response.bodyBytes);
    if (await canLaunch(apkFilePath)) {
      await launch(apkFilePath);
    } else {
      throw 'Could not launch $apkFilePath';
    }
  } else {
    throw 'Failed to download APK';
  }
}

3. 在主应用中使用升级检查函数

最后,在你的主应用入口(如MyAppinitState或某个按钮点击事件中)调用checkForUpdates函数。

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('App Upgrade Example'),
        ),
        body: Center(
          child: Builder(
            builder: (context) {
              return ElevatedButton(
                onPressed: () {
                  checkForUpdates();
                },
                child: Text('Check for Updates'),
              );
            },
          ),
        ),
      ),
    );
  }
}

这个示例代码展示了如何使用upgrade插件(虽然实际上upgrade插件可能提供了更高级的功能,但这里为了演示目的,我们手动实现了逻辑)结合HTTP请求和文件操作来实现应用升级功能。请根据你的实际需求调整代码和API细节。

回到顶部