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();
}
}
最终效果:
本文转自 https://www.cnblogs.com/michong2022/p/17034796.html,如有侵权,请联系删除。在这里插入代码片