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,如有侵权,请联系删除。在这里插入代码片



















