3分钟实现git托管软件安装包,并实现版本检测和更新功能

3分钟实现git托管软件安装包,并实现版本检测和更新功能

  • 最近写了一个开源的壁纸软件,一直想找一个免费好用的安装包托管平台,很遗憾,并未找到,好多平台要么收费、要么不好用。
  • git就不多介绍了,git能够托管代码自然能托管安装包。
  • 问题在于如何通过接口检测更新?只要解决这个问题,其它就都不是问题。

1、git 托管如何通过接口检测更新?

  • 众所周知,json文件是能通过get方式直接获取到的,这个没问题吧,不了解的可以查一下资料。
  • 那么 git 里面的json文件能直接读取吗?我以 gitee 为例测试了一下,发现并没有问题,用户能直接通过链接访问到git托管的json的文件内容。gitee没问题,github等其它代码托管平台应该也没问题,我是懒得测其它平台,有兴趣的可以自己一下。
  • 测试地址: gitee.com/zsnoin-can/...

gitee 获取托管的json文件的连接

  • 初始化git仓库这种基础操作就不说了,直接看结构,只有一个 json(版本信息文件)和 apk 安装包文件。
  • 注意点:仓库需要开源,不然别人无法访问。
  1. 点击json文件,查看json文件内容
  2. 点击右侧原始数据按钮,跳转新页面
  3. copy新页面的地址,通过get请求就能直接获取到json文件的内容了。
  4. json文件内容,你就可以完全自定义了,有新版本时更新版本号和更新日志即可。
  5. 刚开始,我不是通过这种方式获取到地址的,忘了一开始是咋获取到的,应该还有其它方法也可以获取到json地址。

有了版本信息接口和软件地址,只需要对比本地软件版本和git托管的版本是否一致,即可实现软件更新功能。

2、版本检测(flutter为例)

因为壁纸软件是用flutter写的,就以flutter举例,其它像 uniapp、electron 等等都大差不差。

  • package_info_plus 软件包信息管理插件,可以简单快速获取到当前版本号
  • url_launcher 跳转浏览器插件,gitee托管并不能直接下载,需跳转浏览器让用户自行下载。

下载函数,我这用的是自己封装过的Dio发起的网络请求,你可以直接用Dio或者http。

csharp 复制代码
Future<Response> updateApp() => DioInstance.instance().get(
      path:
          'https://gitee.com/zsnoin-can/new-wall-paper-apk/raw/master/version.json',
      param: {
        'random': Random().nextDouble(),
      },
    );

封装更新工具 /tools/update_apk.dart,添加 displayTips 控制没有检测到新版本时是否提示用户。

dart 复制代码
import 'package:bot_toast/bot_toast.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:wallpaper/api/foot.dart';
import 'package:wallpaper/components/button/normal_button.dart';
import 'package:wallpaper/generated/l10n.dart';

class UpdateApk {
  String updateUrl =
      'https://gitee.com/zsnoin-can/new-wall-paper-apk/blob/master/wallpaper.apk';

  Future updateApk(BuildContext context, {bool displayTips = false}) async {
    Response res = await updateApp();
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    String version = packageInfo.version; // 获取版本号
    if (version != res.data['version']) {
      showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Row(
                crossAxisAlignment: CrossAxisAlignment.end,
                spacing: 5,
                children: [
                  Icon(Icons.update, color: Colors.deepOrangeAccent),
                  Text(
                    S.of(context).s15,
                    style: TextStyle(
                      fontSize: 18,
                    ),
                  ),
                  Text(
                    '${res.data['version']}',
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.primary,
                      fontSize: 16,
                    ),
                  ),
                ],
              ),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(5)),
              ),
              content: SizedBox(
                height: 100,
                child: Padding(
                  padding: const EdgeInsets.only(left: 10, right: 10),
                  child: ListView.builder(
                      itemCount: res.data['update'].length,
                      itemBuilder: (context, index) {
                        return Text(
                            "${index + 1}、${res.data['update'][index]}");
                      }),
                ),
              ),
              actions: [
                NormalButton(
                    radius: 5,
                    width: 100,
                    height: 30,
                    fontSize: 16,
                    title: S.of(context).b7,
                    bgColor: const Color.fromARGB(131, 158, 158, 158),
                    onPressed: () {
                      Navigator.pop(context);
                    }),
                NormalButton(
                    radius: 5,
                    width: 100,
                    height: 30,
                    fontSize: 16,
                    title: S.of(context).s16,
                    onPressed: () async {
                      // 打开浏览器更新
                      if (await canLaunchUrl(Uri.parse(updateUrl))) {
                        await launchUrl(Uri.parse(updateUrl));
                      } else {
                        // 如果无法打开链接,显示错误提示
                        ScaffoldMessenger.of(context).showSnackBar(
                          SnackBar(content: Text('url error: $updateUrl')),
                        );
                      }
                      Navigator.pop(context);
                    }),
              ],
            );
          });
    }
    if (version == res.data['version'] && displayTips) {
      BotToast.showText(text: S.of(context).s17);
    }
  }
}

用法:

  • 未检测到新版本时不需要提示 UpdateApk().updateApk(context);,例如,用户进入软件时自动检测更新,未检测到时无需提醒。
  • 未检测到新版本时需要提示 UpdateApk().updateApk(context, displayTips: true);,例如,用户在设置中手动点击了检测更新按钮,未检测到新版本时需要给用户正反馈。

效果图:

3、优缺点

  • 优点:非常简单,基本不需要任何操作就能对软件进行更新功能实装,增加软件的健全性。
  • 缺点:软件没有办法直接下载,安装包属于大文件范畴了,gitee需要用户登录后才能下载。

4、链接

相关推荐
ThinkPet3 小时前
【005安卓开发方案调研】之Flutter+Dart技术开发安卓
android·flutter·跨平台·dart
code_talking5 小时前
Git使用
git
AI视觉网奇6 小时前
vscode git 管理
ide·git·vscode
月明泉清6 小时前
flutter doctor提示cmdline-tools component is missing错误的解决
flutter
阿卡好可爱9 小时前
git原理与常用命令及其使用
git
爱学习的大牛12315 小时前
如何在 Flutter 中使用 WebRTC
flutter·webrtc
AI视觉网奇18 小时前
git 设置保存密码 git保存密码
git
米心18 小时前
Flutter 快速接入Fair
flutter
leluckys18 小时前
flutter 专题 九十 四 Flutter开发之基础知识
flutter
消失的旧时光-194318 小时前
浅谈跨平台框架的演变(H5混合开发->RN->Flutter)
android·开发语言·flutter·react native·跨平台