JavaFX桌面应用-版本升级
好久没有写博客,2021年就以 “JavaFX桌面应用-版本升级” 开篇吧,记录一下JavaFX应用版本升级的开发流程。
桌面应用升级的方案应该很多,这里只是自己想到的方案。
1. 效果展示
首先,先看一下版本升级的最终效果(先不讨论UI美不美观的问题,UI美化可以查看其他博客)
如上图,程序启动后会自动检测是否有最新版本,如果用则提示用户,由用户决定是否进行应用升级,如果用户点击了升级,则会启动升级程序进行升级,并在升级后重新启动新版的APP。
2. 升级流程
在展开说明具体的功能开发前,简单介绍一下应用升级的流程,以及涉及的各个端。
这里的应用升级主要涉及3个方面:
- App(主应用)
- 升级SDK(封装升级流程,App集成即可)
- 升级程序(负责App升级)
应用升级的流程其实比较简单,大致分为这几个步骤:
- 获取最新版本信息
- 询问用户是否升级
- 执行版本升级
升级的流程如下图所示:
3. 升级细节
在上面的升级流程看起来没有什么问题,但实际应用起来有一些细节需要注意,比如:
- 版本怎么计算
- 升级程序怎么获取更新包
- 升级程序怎么打开APP
一般来说,升级程序开发完成后可能很少修改,或者说,希望只开发一个升级程序,供所有app升级使用,这样就不需要为每一个应用都开发一个升级程序。
上图是升级程序获取更新包的流程,这里SDK和升级程序是通过本地文件update_info
作为通讯的媒介,具体的流程为:
- APP启动后调用SDK向服务器拉取版本信息,并将拉取版本信息的地址写入到本地文件
update_info
中 - 如果发现有新版本,并且用户同意升级,那么启动升级程序
- 升级程序启动后,从本地文件
update_info
读取获取获取版本信息的地址,从服务器获取版本信息及更新包,执行版本更新
这里为什么需要SDK每一次都把获取版本信息的地址写入到本地文件中呢?就如上面所说的,升级程序可以是通用的,但每一个APP获取版本信息的地址是不同的,另外同一个APP不同版本获取版本信息的地址也可能是不同的(比如服务器在某个时间点更换了域名等等)。
升级程序和SDK的通讯解决了,整理流程也没有什么大问题,那么版本应该怎么计算呢?
最简单的处理方式就是,发现版本号不一样时就升级,这种方式不是不可以,但是可能会有很多问题,因为有些时候APP可能更新了一些不兼容旧版的功能,对于兼容的情况可以选择增量更新APP,而对于不兼容的情况就需要全量更新APP了,而且不排除让用户重新安装程序的情况。
这里介绍一下自己使用的一种方案,版本号规范约定为 x.y.z
,客户端APP将x.y.z转化为整数(x*100+y*10+z)与服务器返回的版本进行比较,如果APP的版本小于服务版本则进行升级,服务端可以根据客户端提供的x.y.z提供合适的升级版本信息及更新包。
版本计算简要代码如下:
private int versionToInt(String version) {
String[] items = version.split("\\.");
int versionInt = 0;
for (String item : items) {
versionInt *= 10;
versionInt += Integer.parseInt(item.trim());
}
return versionInt;
}
所以每一个APP都得提供自己的版本号以及获取最新版本的接口地址,这个可以在APP通过定义一些常量来记录:
public interface Version {
// 获取版本的接口地址
String versionUri = "http://localhost:8090/itqn/version";
// 当前版本号
String version = "1.0.0";
}
这样,程序就可以每次启动后获取自己版本号,再从服务器获取版本信息计算是否需要升级,但是这样对有“跳过版本”这种升级流程来说是有问题的,按照上面的流程,当用户点击了“跳过版本”后,下次启动APP时,从服务器获取升级信息计算后仍需要升级,会弹出升级提示,这样很不友好。
这里稍微调整一下读取版本的流程:
- 用户点击跳过版本后,将最新版本号写入到本地文件
version
中 - APP正常升级后,升级程序也将最新版本号写入到本地文件
version
中 - 程序启动的时候,优先读取本地文件
version
的版本号进行计算,如果本地没有version
文件,才读取APP版本号常量
对应的版本计算实现代码如下:
private void checkVersion() {
int curVersion = 0;
File f = new File("version");
char[] buf = new char[30];
try (FileReader fr = new FileReader(f)) {
int ret = fr.read(buf);
curVersion = versionToInt(new String(buf, 0, ret));
} catch (Exception ignore) {
// use AppVersion if occur exception
}
if (curVersion == 0) {
curVersion = versionToInt(Version.version);
}
UpdateExecutor.execute(Version.versionUri, curVersion);
}
最后,关于升级程序怎么打开APP这个问题可以参考升级程序和SDK的通讯方案。当然也用更新简单的方案,就是升级程序打开非自己名称的exe应用,这种方式只能用于应用程序只有一个exe文件的情况。
// 这里ITQN_update是升级程序的名称
File[] fs = new File(".").listFiles((dir, name) -> name.endsWith(".exe") && !name.equals("ITQN_update.exe"));
if (fs != null && fs.length > 0) {
try {
Desktop.getDesktop().open(fs[0]);
} catch (IOException e) {
new Alert(Alert.AlertType.ERROR, e.getMessage()).show();
}
}
应用升级这一块涉及的问题比较多,更多的细节可以通过公众号获取源码,具体阅读源码吧,展开说明的话太多了。
=========================================================
关注 公众号 “HiIT青年” 阅读推文“JavaFX桌面应用-版本升级”,文章底部可以获取源码。
关注公众号,阅读更多文章。
JavaFX桌面应用-版本升级的更多相关文章
- JavaFX桌面应用-MVC模式开发,“真香”
使用mvc模块开发JavaFX桌面应用在JavaFX系列文章第一篇 JavaFX桌面应用开发-HelloWorld 已经提到过,这里单独整理使用mvc模式开发开发的流程. ~ JavaFX桌面应用开发 ...
- JavaFX桌面应用开发-HelloWorld
JavaFX是一个强大的图形和多媒体处理工具包集合,它允许开发者来设计.创建.测试.调试和部署富客户端程序,并且和Java一样跨平台. JavaFX比Swing好用很多,它允许开发使用FXML来设计和 ...
- JavaFX桌面应用-为什么应用老是“未响应”
日常使用软件的过程中,偶尔会遇到软件突然卡住,再点击几次就变成"未响应"的情况. 在JavaFX应用中同样也会出现这种情况,在开发过程中应该尽量避免这种情况的出现. >> ...
- JavaFX桌面应用开发系列文章
~ JavaFX桌面应用开发系列文章汇总篇 ~ JavaFX桌面应用开发-HelloWorld JavaFX布局神器-SceneBuilder JavaFX让UI更美观-CSS样式 JavaFX桌面应 ...
- JavaFX桌面应用-视频转码工具(支持爱奇艺qsv转mp4)
最近由于需要将在爱奇艺下载的视频(qsv)转化了mp4,用JavaFX开发一个视频转码工具,算是JavaFX开发的第一个应用吧. 支持qsv转码mp4,理论上支持各种格式,仅测试了flv,qsv格式. ...
- JavaFX桌面应用-loading界面
上次使用JavaFX开发了一个视频转码工具,当用户点击"启动"按钮开始转码的时候,会禁用启动按钮,防止多次启动转码. 这种处理方式对用户来说可能并是很友好,其实可以在启动转码的时弹 ...
- JavaFX桌面应用-SpringBoot + JavaFX
SpringBoot对于Java程序员来说可以是一个福音,它让程序员在开发的时候,大大简化了各种spring的xml配置. 那么在JavaFX项目使用SpringBoot会是怎么样的体验呢? 这次使用 ...
- JavaFX桌面应用-构建程序框架
看到JavaFX应用很多人都会说JavaFX应用太丑了,确实JavaFX比起Qt.MFC.Delphi这些界面确实丑了一点,但也不是没有可以美化的空间. 跟网页一样,单纯HTML不加任何CSS的时候也 ...
- JavaFX桌面应用开发-鼠标事件和键盘事件
鼠标相关事件的操作初始代码 package application; import javafx.application.Application;import javafx.event.ActionE ...
随机推荐
- C# 使用PictureBox实现图片按钮控件
引言 我们有时候会在程序的文件夹里看见一些图标,而这些图标恰好是作为按钮的背景图片来使用的.鼠标指针在处于不同状态时,有"进入按钮"."按下左键"," ...
- 2019 Multi-University Training Contest 2 I.I Love Palindrome String(回文自动机+字符串hash)
Problem Description You are given a string S=s1s2..s|S| containing only lowercase English letters. F ...
- Codeforces Round #664 (Div. 2) C. Boboniu and Bit Operations
传送门:cf1395C 题意 c[i]=a[i]&b[j],b[j]是b数组中任意一个,求c[1] | c[2] | ... | c[n]最小值. 题解 经典的二进制枚举答案,因为a和b的最大 ...
- Codeforces ECR 83 C. Adding Powers (位运算)
题意:给你n个数和一个底数k,每个数每次能减去k^i(i=0,1,2,....),每个k^i只能用一次,问是否能够将每个数变为0. 题解:我们将每个数转化为k进制,因为每个k^i只能用一次,所以我们统 ...
- XHXJ's LIS HDU - 4352 最长递增序列&数位dp
代码+题解: 1 //题意: 2 //输出在区间[li,ri]中有多少个数是满足这个要求的:这个数的最长递增序列长度等于k 3 //注意是最长序列,可不是子串.子序列是不用紧挨着的 4 // 5 // ...
- word2vector代码实践
引子 在上次的 <word2vector论文笔记>中大致介绍了两种词向量训练方法的原理及优劣,这篇咱们以skip-gram算法为例来代码实践一把. 当前教程参考:A Word2Vec Ke ...
- MySQL 事务特征 & 隔离级别
数据库事务特征 Atomicity 原子性 事务是一个原子性质的操作单元,事务里面的对数据库的操作要么都执行,要么都不执行, Consistent 一致性 在事务开始之前和完成之后,数据都必须保持一致 ...
- Keepalived+LVS实现LNMP网站的高可用部署
Keepalived+LVS实现LNMP网站的高可用部署 项目需求 当我们访问某个网站的时候可以在浏览器中输入IP或者域名链接到Web Server进行访问,如果这个Web Server挂了, ...
- Leetcode(869)-重新排序得到 2 的幂
从正整数 N 开始,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零. 如果我们可以通过上述方式得到 2 的幂,返回 true:否则,返回 false. 示例 1: 输入:1 输出 ...
- SQL优化汇总
今天面某家公司,然后问我SQL优化,感觉有点忘了,今天特此总结一下: 总结得是分两方面:索引优化和查询优化: 一. 索引优化: 1. 独立的列 在进行查询时,索引列不能是表达式的一部分,也不能是函数的 ...