Flutter之自动更新(自带源码 包看包会)

Flutter做的App怎么自动更新呢 首先要用到两个依赖一个叫update_app
另外一个叫package_info
还有一个叫Dio
一个是用来下载App的 一个是用来获取当前App的版本信息的 一个是用来网络链接的

flutter pub add update_app
flutter pub add package_info
flutter pub add dio

然后上代码

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:update_app/bean/download_process.dart';

import 'package:update_app/update_app.dart';

void main() => runApp(MyApp());
//为什么我要先用StatelessWidget  再用StatefulWidget 的呢  因为如果不这样 会报错误 找不到父类的祖宗Context

class MyApp extends StatelessWidget {
  
  _MyAppState createState() => _MyAppState();

  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(), // here pass parameter
    );
  }
}

class HomePage extends StatefulWidget {
  
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<HomePage> {
  //定时更新进度
  Timer? timer;

  //下载进度
  double downloadProcess = 0;

  //下载状态
  String downloadStatus = "";

  
  void initState() {
    super.initState();
       SchedulerBinding.instance!.addPostFrameCallback((_) => {ifUpdate(context)});
  }

  Future<void> ifUpdate(BuildContext buildContext) async {
    var s = "http://你的后端链接获取你设置App的版本号";
    var dio = Dio();
    final response = await dio.get(s);
    print(response.data);
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    //如果你设置的版本号 于你本机上的App的版本号 不一致 弹出下载框
    if (response.data != packageInfo.version) {
      print(packageInfo.version);
      updatedialog.showUpdateDialog(buildContext, '有新版本发布\n2.请更新', false);
    }
  }

  
  Widget build(BuildContext? context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Update app'),
        ),
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Container(
                padding: EdgeInsets.all(16),
                width: 200,
                height: 200,
                child: CircularProgressIndicator(
                  value: downloadProcess,
                  strokeWidth: 10,
                ),
              ),
              Text("Download status: $downloadStatus"),
              Text("Please replace the download url with your own address"),
            ],
          ),
        ),
        bottomNavigationBar: Container(
            padding: EdgeInsets.all(20),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  '点击右下角的下载按钮下载!',
                  style: TextStyle(color: Theme.of(context!).primaryColor),
                ),
              ],
            )),
        floatingActionButton: FloatingActionButton(
          onPressed: download,
          child: Icon(Icons.file_download),
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
      ),
    );
  }

  
  void dispose() {
    timer?.cancel();
    super.dispose();
  }

  void download() async {
    var downloadId = await UpdateApp.updateApp(
        url:
            "https://你app的下载地址",
        );

    //本地已有一样的apk, 下载成功
    if (downloadId == 0) {
      setState(() {
        downloadProcess = 1;
        downloadStatus = ProcessState.STATUS_SUCCESSFUL.toString();
      });
      return;
    }

    //出现了错误, 下载失败
    if (downloadId == -1) {
      setState(() {
        downloadProcess = 1;
        downloadStatus = ProcessState.STATUS_FAILED.toString();
      });
      return;
    }

    //正在下载文件
    timer = Timer.periodic(Duration(milliseconds: 100), (timer) async {
      var process = await UpdateApp.downloadProcess(downloadId: downloadId);
      //更新界面状态
      setState(() {
        downloadProcess = process.current / process.count;
        downloadStatus = process.status.toString();
      });

      if (process.status == ProcessState.STATUS_SUCCESSFUL ||
          process.status == ProcessState.STATUS_FAILED) {
        //如果已经下载成功, 取消计时
        timer.cancel();
      }
    });
  }
}

下面是弹窗widgt 你们可以自己修改 或者自己写一个

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:translateapp/CommonUtils/toast_helper.dart';
import 'package:translateapp/main.dart';

///update by zah
///on 2023/1/7
///description:版本更新提示弹窗
class updatedialog extends Dialog {
  final String upDateContent = "";
  final bool isForce = false;

  updatedialog({Key? key, required String upDateContent, required bool isForce})
      : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              color: Colors.blue,
              /*         decoration: BoxDecoration(
                color: backgroundColor,
                border: Border.all(color: Colors.white60),
                shape: BoxShape.circle,
              ),*/
              width: MediaQuery.of(context).size.width -
                  (MediaQuery.of(context).size.width / 4),
              /* height: ,*/
              child: Stack(
                children: <Widget>[
/*                Image.asset(
                    AssetsUtil.getImagePath(
                        imageName: 'bg_update', suffix: 'png'),
                    fit: BoxFit.cover,
                  ),*/
                  Container(
                    width: double.infinity,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Container(
                          margin: const EdgeInsets.only(top: 10),
                          child: const Text('发现新版本',
                              style: TextStyle(
                                  fontSize: 14,
                                  color: Colors.white,
                                  decoration: TextDecoration.none)),
                        ),
                        Text(upDateContent,
                            style: TextStyle(
                                fontSize: 14,
                                color: Colors.black54,
                                decoration: TextDecoration.none)),
                        Container(
                          width: 100,
                          height: 100,
                          margin: EdgeInsets.only(bottom: 10),
                          child: RaisedButton(
                              color: Colors.red,
                              shape: StadiumBorder(),
                              child: Text(
                                '立即更新',
                                style: TextStyle(
                                    fontSize: 14, color: Colors.white),
                              ),
                              onPressed: () {
                                HomePage home = new HomePage();
                                home.createState().download();
                                Navigator.pop(context);
                              }),
                        )
                      ],
                    ),
                  ),
                ],
              ),
            ),
            GestureDetector(
              onTap: () {
                exit(0);
              },
              child: Offstage(
                offstage: isForce,
                child: Container(
                  margin: EdgeInsets.only(top: 10),
                  child: Icon(
                    Icons.cancel,
                    size: 54,
                    color: Colors.white,
                  ),
                  /*    Image.asset(
                      AssetsUtil.getImagePath(
                          imageName: 'ic_update_close', suffix: 'png'),
                      width:100 ,
                      height: ,100
                    )*/
                ),
              ),
            )
          ],
        ),
      ),
    );
  }

  static showUpdateDialog(
      BuildContext context, String mUpdateContent, bool mIsForce) {
    return showDialog(
        barrierDismissible: false,
        context: context,
        builder: (BuildContext context) {
          return WillPopScope(
              child: updatedialog(
                  upDateContent: mUpdateContent, isForce: mIsForce),
              onWillPop: _onWillPop);
        });
  }

  static Future<bool> _onWillPop() async {
    return false;
  }
}

效果如下
在这里插入图片描述
对了 最后 还有一点 下载的文件 如果它不安装 直接把它下载的文件删掉 由于依赖没有这个方法 我自己加了下去 就一句代码而已
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值