JavaFX桌面應用-版本升級

HiIT青年發表於2021-02-28

好久沒有寫部落格,2021年就以 “JavaFX桌面應用-版本升級” 開篇吧,記錄一下JavaFX應用版本升級的開發流程。

桌面應用升級的方案應該很多,這裡只是自己想到的方案。

1. 效果展示

首先,先看一下版本升級的最終效果(先不討論UI美不美觀的問題,UI美化可以檢視其他部落格)

如上圖,程式啟動後會自動檢測是否有最新版本,如果用則提示使用者,由使用者決定是否進行應用升級,如果使用者點選了升級,則會啟動升級程式進行升級,並在升級後重新啟動新版的APP。

2. 升級流程

在展開說明具體的功能開發前,簡單介紹一下應用升級的流程,以及涉及的各個端。

這裡的應用升級主要涉及3個方面:

  • App(主應用)
  • 升級SDK(封裝升級流程,App整合即可)
  • 升級程式(負責App升級)

應用升級的流程其實比較簡單,大致分為這幾個步驟:

  1. 獲取最新版本資訊
  2. 詢問使用者是否升級
  3. 執行版本升級

升級的流程如下圖所示:

3. 升級細節

在上面的升級流程看起來沒有什麼問題,但實際應用起來有一些細節需要注意,比如:

  • 版本怎麼計算
  • 升級程式怎麼獲取更新包
  • 升級程式怎麼開啟APP

一般來說,升級程式開發完成後可能很少修改,或者說,希望只開發一個升級程式,供所有app升級使用,這樣就不需要為每一個應用都開發一個升級程式。

上圖是升級程式獲取更新包的流程,這裡SDK和升級程式是通過本地檔案update_info作為通訊的媒介,具體的流程為:

  1. APP啟動後呼叫SDK向伺服器拉取版本資訊,並將拉取版本資訊的地址寫入到本地檔案update_info
  2. 如果發現有新版本,並且使用者同意升級,那麼啟動升級程式
  3. 升級程式啟動後,從本地檔案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時,從伺服器獲取升級資訊計算後仍需要升級,會彈出升級提示,這樣很不友好。

這裡稍微調整一下讀取版本的流程:

  1. 使用者點選跳過版本後,將最新版本號寫入到本地檔案version
  2. APP正常升級後,升級程式也將最新版本號寫入到本地檔案version
  3. 程式啟動的時候,優先讀取本地檔案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桌面應用-版本升級”,文章底部可以獲取原始碼。

HiIT青年
關注公眾號,閱讀更多文章。

相關文章