Flutter App更新升级

1. 应用程序升级流程

由于在 IOS 中没法直接下载安装,如果版本不一致则直接跳转到IOS应用对应的应用市场就可以了,所以本文仅介绍Android App的升级流程。

Android App升级流程:

1. 获取本地版本号;

2. 请求服务器获取服务器版本号;

3. 如果本地版本和服务器版本不一致则提示升级,弹窗提示用户是否更新;

4. 用户确定升级,调用文件传输方法下载apk文件;

5. 监听下载进度;

6. 下载完成打开apk进行安装。

2. Android 升级 App 涉及的 API 库

  # app升级
  package_info_plus: ^1.4.3+1
  ota_update: ^4.0.1
  url_launcher: ^6.1.5
  progress_dialog_null_safe: ^1.0.7

3.在Android文件夹里面增加如下文件

4.filepaths文件里面的代码

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external-path"
        path="."/>
    <external-cache-path
        name="external-cache-path"
        path="."/>
    <external-files-path
        name="external-files-path"
        path="."/>
    <files-path
        name="files_path"
        path="."/>
    <cache-path
        name="cache-path"
        path="."/>
    <root-path
        name="name"
        path="."/>
</paths>

 5.在AndroidManifest.xml里面添加如下代码

    <!--网络权限-->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 <!--存储-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- 必要权限,安装权限 -->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

在application里面添加如下代码

<provider
            android:name="sk.fourq.otaupdate.OtaUpdateFileProvider"
            android:authorities="${applicationId}.ota_update_provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true"
            tools:replace="android:authorities">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"
                tools:replace="android:resource"/>
        </provider>

6.下面是更新app使用的代码片段

 /// 检查更新
  //定义apk的名称,与下载进度dialog
  String apkName = 'flutterApp.apk';
  String progress = "";
  late ProgressDialog pr;

  Future<void> doCheck() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    String appName = packageInfo.appName;
    String packageName = packageInfo.packageName;
    String version = packageInfo.version;
    String buildNumber = packageInfo.buildNumber;
    String deviceType = "";
    // 应用名称
    print("appName:${appName}");
// 包名称
    print("packageName:${packageName}");
// 版本号
    print("version:${version}");
// 构建编号
    print("buildNumber:${buildNumber}");
    sp.setString('app_version', version);
    if (Platform.isAndroid) {
      deviceType = "Android";
    } else {
      deviceType = "ios";
    }
    var params = <String, dynamic>{
      'packageName': packageName,
      'system': deviceType,
    };
    try {
      CheckoutBeanEntity checkVersionBeanEntity =
          await DataUtils.checkVersion(params);
      switch (checkVersionBeanEntity.code) {
        case MyHttpConfig.successCode:
          if (int.parse(buildNumber) <
              checkVersionBeanEntity.data.versionCode) {
            if (Platform.isAndroid) {
              // ignore: use_build_context_synchronously
              showUpdate(
                  context,
                  checkVersionBeanEntity.data.versionCode.toString(),
                  checkVersionBeanEntity.data.fileUrl,
                  checkVersionBeanEntity.data.description);
            } else {
              const url =
                  "https://itunes.apple.com/cn/app/id1380512641"; // id 后面的数字换成自己的应用 id 就行了
              if (await canLaunch(url)) {
                await launch(url, forceSafariVC: false);
              } else {
                throw 'Could not launch $url';
              }
            }
          }
          break;
        default:
          MyToastUtils.showToastBottom(checkVersionBeanEntity.msg);
          break;
      }
    } catch (e) {
      // MyToastUtils.showToastBottom("网络异常");
    }
  }

  /// 显示更新内容
  Future<void> showUpdate(
      BuildContext context, String version, String url, String info) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false, //设置为false,点击空白处弹窗不关
      builder: (BuildContext context) {
        return CupertinoAlertDialog(
          title: Text('检测到新版本 v$version'),
          content: Text(
            info,
            style:  TextStyle(
              fontSize: ScreenUtil().setSp(30),
            ),
          ),
          actions: <Widget>[
            FlatButton(
              child: const Text('下次在说'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: const Text('立即更新'),
              onPressed: () => doUpdate(context, version, url),
            ),
          ],
        );
      },
    );
  }

  ///3.执行更新操作
  doUpdate(BuildContext context, String version, String url) async {
    //关闭更新内容提示框
    Navigator.pop(context);
    // downloadAndroid(url);
    _updateVersion(url);
  }

  /// android app更新
  void _updateVersion(String url) async {
    pr = ProgressDialog(
      context,
      showLogs: true,
      type: ProgressDialogType.download, //下载类型带下载进度
      isDismissible: false, //点击外层不消失
    );
    if (!pr.isShowing()) {
      pr.show();
    }
    try {
      // destinationFilename 是对下载的apk进行重命名
      OtaUpdate().execute(url, destinationFilename: 'hbgspad.apk').listen(
        (OtaEvent event) {
          print('status:${event.status},value:${event.value}');
          switch (event.status) {
            case OtaStatus.DOWNLOADING: // 下载中
              setState(() {
                progress = event.value!;
                double d = double.parse(progress);
                pr.update(
                  progress: d,
                  message: "下载中,请稍后…",
                );
              });
              break;
            case OtaStatus.INSTALLING: //安装中
              if (pr.isShowing()) {
                pr.hide();
              }
              break;
            case OtaStatus.PERMISSION_NOT_GRANTED_ERROR: // 权限错误
              print('更新失败,请稍后再试');
              if (pr.isShowing()) {
                pr.hide();
              }
              break;
            default: // 其他问题
              break;
          }
        },
      );
    } catch (e) {
      print('更新失败,请稍后再试');
    }
  }

7.里面组件报错的话,不要担心,因为那个都是自己定义的,只要替换成正常自己的代码提示请求方式和解析返回结果就可以了。

最后就能实现更新app功能了,喜欢的话留个赞吧

猜你喜欢

转载自blog.csdn.net/as425017946/article/details/127409649