flutter 升级 IOS Android app内部

第一步 导入三个库

 path_provider: ^1.1.0                         #文件路径

  ota_update: ^4.0.1       #下载文件

  open_file: ^2.0.3     #打开文件

然后pug get下

第二步 配置安卓AndroidManifest

                1.添加provider

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

        2.添加权限

 <uses-permission android:name="android.permission.INTERNET"/>
    <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" />

第三步 widget中下载文件 

class UpdaterAppPage extends BaseStatefulWidget {
  final Widget child;

  const UpdaterAppPage(this.child);

  @override
  BaseStatefulWidgetState<BaseStatefulWidget> getState() {
    return UpdaterAppApageState();
  }
}

class UpdaterAppApageState extends BaseStatefulWidgetState<UpdaterAppPage>
    with UpdateCallBack {
  var _serviceVersionCode,
      _serviceVersionContent,
      _serviceVersionPlatform,
      _type,
      _serviceVersionApp;

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }

  @override
  void initState() {
    super.initState();
    _getNewVersionAPP();
  }

  //执行版本更新的网络请求
  _getNewVersionAPP() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    String _currentVersionCode = packageInfo.version;
    var map = HashMap<String, dynamic>();
    map["appVersion"] = _currentVersionCode; //版本号
    map["clientType"] = Platform.isAndroid ? 0 : 1; //获取设备类型 0安卓 1 ios
    TeamService.requestUpgrade(map, (response) async {
      if (response != null) {
        setState(() {
          Data data = response.data;
          _serviceVersionCode = data.lastVersion; //版本号
          _serviceVersionContent = data.content; //版本名称
          _serviceVersionApp = data.downloadUrl; //下载的URL
          _type = data.type;
          if (_type != 0) {
            _showNewVersionAppDialog();
          }
        });
      }
    }, (error) async {});
  }

  var downLoading = "立即更新";
  var _setState;

  BuildContext? buildContext;

  //弹出"版本更新"对话框
  Future<void> _showNewVersionAppDialog() async {
    showGeneralDialog(
      context: context,
      pageBuilder: (context, anim1, anim2) {
        buildContext = context;
        return WillPopScope(
            child:
                UpdateWidget(this, _type, downLoading, _serviceVersionContent),
            onWillPop: () async {
              return Future.value(_type==1?false:true);
            });
      },
      barrierColor: Colors.grey.withOpacity(.4),
      barrierDismissible: _type==1?false:true,
      barrierLabel: "",
      transitionDuration: Duration(milliseconds: 125),
    );
  }

  @override
  void callBack() {
    _downLoad();
  }

  @override
  void dismiss() {
    if (buildContext != null) {
      Navigator.pop(buildContext!);
    }
  }

//下载并打开文件
  _downLoad() async {
    // 获取APP安装路径
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String appDocPath = appDocDir.path;

    if (Platform.isIOS) {
      String url =
          'https://apps.apple.com/cn/app/%E9%87%8F%E5%8C%96%E4%BA%91/id1558978023'; //到时候换成自己的应用的地址
      // 通过url_launcher插件来跳转AppStore
      // if (await canLaunch(url)){
      launch(url);
      // }else {
      //   throw 'Could not launch $url';
      // }
    } else if (Platform.isAndroid) {
      var fileName = "scr_app.apk";
      try {
        try {
          //LINK CONTAINS APK OF FLUTTER HELLO WORLD FROM FLUTTER SDK EXAMPLES
          OtaUpdate()
              .execute(
            _serviceVersionApp,
            // OPTIONAL
            destinationFilename: fileName,
            //OPTIONAL, ANDROID ONLY - ABILITY TO VALIDATE CHECKSUM OF FILE:
          )
              .listen(
            (OtaEvent event) {
              print("${event.value}|${event.status}");
              switch (event.status) {
                case OtaStatus.DOWNLOADING: //下载中
                  eventBus
                      .fire(EventFn(EventConstant.downLoading, event.value));
                  break;
                case OtaStatus.INSTALLING:
                  eventBus.fire(EventFn(EventConstant.downSuccess, ""));
                  OpenFile.open("${appDocPath}/${fileName}");
                  break;
                case OtaStatus.PERMISSION_NOT_GRANTED_ERROR:
                  CommonToast.show("由于缺少权限,无法继续");
                  break;
                default:
                  eventBus.fire(EventFn(EventConstant.downError, ""));
                  break;
              }
            },
          );
        } catch (e) {
          print('Failed to make OTA update. Details: $e');
        }
      } catch (e) {
        print('更新失败,请稍后再试');
      }
    }
  }
}

上边的对话框是我自己自定义的  我也贴下代码 

class UpdateWidget extends BaseStatefulWidget {
  UpdateCallBack update;
  int type;
  String downLoading;
  String content;

  UpdateWidget(this.update, this.type, this.downLoading, this.content);

  @override
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  @override
  BaseStatefulWidgetState<BaseStatefulWidget> getState() {
    return UpdateWidgetState();
  }
}

class UpdateWidgetState extends BaseStatefulWidgetState<UpdateWidget> {
  var downLoading = "立即下载";
  bool isClick = false; //默认可以点击  下载中无法再次点击
  var eventBusFn;

  @override
  void initState() {
    super.initState();
    eventBusFn = eventBus.on<EventFn>().listen((event) {
      //全局通知接收器
      if (event.eventCode == EventConstant.downLoading) {
        //下载中
        isClick = true;
        downLoading = "正在下载中..." + event.eventMsg + "%";
        stateSetter(() {});
      } else if (event.eventCode == EventConstant.downSuccess) {
        //下载完成
        isClick = false;
        setState(() {
          downLoading = "已下载完成";
        });
      } else if (event.eventCode == EventConstant.downSuccess) {
        //失败
        setState(() {
          downLoading = "下载失败";
        });
        isClick = false;
      }
    });
  }

  var count = 0;
  var _list = [const Color(0xff4E46F4), const Color(0xff3241CC)];
  var stateSetter;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      margin: EdgeInsets.only(left: kScale(52), right: kScale(52)),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            width: double.infinity,
            child: Image.asset(
              'assets/images/icon_update_head.png',
              fit: BoxFit.fitWidth,
            ),
          ),
          Container(
            transform: Matrix4.translationValues(0.0, -2.0, 0.0),
            decoration: BoxDecoration(
                color: kColor.white,
                borderRadius: const BorderRadius.only(
                    bottomLeft: Radius.circular(25),
                    bottomRight: Radius.circular(25))),
            child: Column(
              children: [
                Container(
                  margin: EdgeInsets.only(top: kScale(22),left: kScale(15),right: kScale(15)),
                  alignment: Alignment.center,
                  color: kColor.white,
                  width: double.infinity,
                  child: Text(
                    widget.content,
                    style:
                        TextStyle(fontSize: kScale(16), color: kColor.tabColor),
                  ),
                ),

                GestureDetector(
                  onTap: () {
                    if (isClick) return;
                    if (widget.update != null) {
                      widget.update.callBack();
                    }
                  },
                  child: Container(
                    decoration: BoxDecoration(
                        border: Border.all(color: kColor.update_border),
                        gradient: LinearGradient(colors: _list),
                        borderRadius: BorderRadius.circular(13)),
                    width: double.infinity,
                    margin: EdgeInsets.only(left: kScale(15),right: kScale(15),top: kScale(40),bottom: kScale(15)),
                    height: kScale(45),
                    child: StatefulBuilder(builder: (context, stateSetter) {
                      this.stateSetter = stateSetter;
                      return

                        Container(
                          margin: EdgeInsets.only(
                              left: kScale(21), right: kScale(21)),
                          height: kScale(45),
                          alignment: Alignment.center,
                          child: Text(
                            downLoading,
                            style: TextStyle(
                                fontSize: kScale(17), color: kColor.white),
                          ),
                        )
                      ;
                    }),
                  ),
                )
                ,
                Visibility(
                    visible: widget.type!=1, //强制升级不显示
                    child: GestureDetector(onTap: (){
                      if (widget.update != null) {
                        widget.update.dismiss();
                      }
                    },child: Container(
                      color: kColor.white,
                      width: double.infinity,
                      margin: EdgeInsets.only(bottom: kScale(17.5)),
                      child: Center(
                        child: Text(
                          '退出',
                          style: TextStyle(
                              fontSize: kScale(15), color: kColor.exit),
                        ),
                      ),
                    ),))
              ],
            ),
          )
        ],
      ),
    );
  }
}

abstract class UpdateCallBack {
  void callBack();
  void dismiss();
}

通知使用的eventBus 你也可以用别的 

接下来就是使用 找到main 

 嵌套在Scaffold 外边 我得BaseScaffold我得基类 也说明下,害怕小白不知道  这样大概就可以下载了升级了  接口需要后台支持才能升级的

IOS 只需要打开浏览器  打开appStore就行了 主要是安卓 权限获取 文件下载。

就到这了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我想吃辣条

觉得不错,就可怜可怜博主吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值