JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。
1. 整体方案
JavaFX.应用版本检测、自动更新主要涉及一下步骤:
- 读取本地应用版本
- 拉取远程版本并比较两个版本
- 如果需要升级,那么拉取更新历史
- 弹出升级控制窗口
- 用户选择升级时,拉取升级包解压,重启应用
- 用户选择忽略时,本地版本标志为忽略版本
- 用户选择取消时,隐藏升级控制窗口
2. 版本检测
版本检测功能最好采用JavaFX的Task异步进行,下面是一个实现方案:
class UpgradeTask extends Task<Void> { private final UpgradeBinding binding; private final Properties config; private final String currentVersion; public UpgradeTask(UpgradeBinding binding, String currentVersion) { this.binding = binding; this.currentVersion = currentVersion; config = new Properties(); try (InputStream is = this.getClass().getResourceAsStream("/upgrade.properties")) { config.load(is); } catch (IOException e) { e.printStackTrace(); } } @Override protected Void call() { String versionAPI = config.getProperty("version.api"); String remoteVersion = HTTP.get(versionAPI); if (!Objects.equals(currentVersion, remoteVersion)) { Platform.runLater(() -> { binding.upgrade.set(true); binding.version.set(remoteVersion); }); String changelogAPI = config.getProperty("changelog.api"); String changelog = HTTP.get(changelogAPI); Platform.runLater(() -> binding.changelog.set(changelog)); } return null; } }
升级服务器信息配置在upgrade.properties配置文件中,在主应用打包的时候一起打包。
3. UI.设计
这里只是简单的开发了一个控制窗口,具体可以根据需要进一步完善:
class UpgradeUI { private final UpgradeBinding binding; private final Stage stage; public UpgradeUI(UpgradeBinding binding, Stage owner) { this.stage = new Stage(); this.stage.initOwner(owner); this.binding = binding; } public void show() { Label version = new Label(); version.textProperty().bind(binding.version); TextArea textArea = new TextArea(); textArea.textProperty().bind(binding.changelog); textArea.setDisable(false); Button cancel = new Button("取消"); cancel.setOnMouseClicked(event -> stage.close()); VBox root = new VBox(); root.setPadding(new Insets(20)); root.setSpacing(20); HBox vContainer = new HBox(); vContainer.setSpacing(10); vContainer.setAlignment(Pos.CENTER_LEFT); vContainer.getChildren().addAll(new Label("最新版本:"), version); VBox cContainer = new VBox(); cContainer.setSpacing(10); cContainer.getChildren().addAll(new Label("更新内容:"), textArea); HBox bContainer = new HBox(); bContainer.setSpacing(20); bContainer.setAlignment(Pos.CENTER); bContainer.getChildren().addAll(new Button("更新"), new Button("跳过"), cancel); root.getChildren().addAll(vContainer, cContainer, bContainer); stage.setScene(new Scene((root))); stage.setWidth(320); stage.setHeight(240); stage.setResizable(false); stage.getIcons().clear(); stage.getIcons().add(new Image("logo.jpg")); stage.show(); } }
注意上面仅实现了取消功能,如果需要实现更新和跳过功能需要进一步完善,即整体方案中提到的第5点和第6点。
4. 流程控制
在主进程中异步启动升级检测线程:
public class Sample03 extends Application { @Override public void start(Stage stage) { StackPane root = new StackPane(); root.getChildren().add(new Label("版本:0.1")); stage.setScene(new Scene(root)); stage.setWidth(640); stage.setHeight(480); stage.setTitle("版本检测 + 自动更新"); stage.getIcons().clear(); stage.getIcons().add(new Image("logo.jpg")); stage.show(); UpgradeBinding binding = new UpgradeBinding(); UpgradeUI ui = new UpgradeUI(binding, stage); UpgradeTask task = new UpgradeTask(binding, "0.1"); task.setOnSucceeded(e -> { if (binding.upgrade.get()) { ui.show(); } }); Thread t = new Thread(task); t.setDaemon(true); t.start(); } }
最终效果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)