ホームページ開発ツール>Xojo / Real Studio Trial and Error・もう一つの自動アップデート機能を試す(Kaju編)

 Xojo / Real Studio Trial and Error

もう一つの自動アップデート機能を試す(Kaju編)

目次
 はじめに

 以下は、Xojo Cocoaビルドについての話題です。

 もう一つのXojo向け自動アップデート機能である、Kajuについて、調べてみました。

 なお検証には、Xojo 2021 Release 2.1を用いています。(Mac mini 2018 + macOS 12.2 Monterey)


 経緯

 Macアプリ用自動アップデート機能として、Sparkleが使えることは確認できましたが、この過程でXojoに特化したKajuがヒットしました。

 参考サイト(1):GitHub - ktekinay/Kaju: Xojo code for implementing self-updating apps

 ソース一式は上記サイトからダウンロードできます。ファイルサイズが表示されないので不安でしたが、暫く放置したら終わっていました。
(218MBと、この種のソースとしては結構なサイズですが、Windows用とLinux用のサンプルアプリが170MBを占めていました。)

 眺めるといろいろ入っていますが、Kaju Admin App(またはKaju Admin CLI)は、管理用として使います。
 ここではAppの方をビルドしておきました。(注:当方にはコマンドラインアプリ用のライセンスがありませんので、Kaju Admin CLIは未調査です。)
 Update Test Appは、機能の確認に使えます。起動してCheckボタンを押すと、Kajuが用意したサーバーに接続してアップデート情報が表示されます。

 他に気付いた点は、(1)マルチプラットホーム対応、(2)httpsだけでなくhttpでも接続可能、(3)(Sparkleとは異なり、)アップデート可能なバージョンが複数ある場合は選択できる、(4)<ユーザー名>/ライブラリ/Application Support/にアプリ名でフォルダーが作られてアップデートやスキップするとバージョンが記録される、といったあたりでしょうか。

 さて、自作アプリへの適用ですが、これが思ったより時間が掛かったのは、主に以下の理由からでした。
  1. プロジェクトを立ち上げるとエラーが出る
     Kaju Admin App : IDE Scriptリンクエラー(全て、Build Automation.xojo_codeを指定すればOK?)
     Update Test App : IDE Scriptリンクエラー(全て、Build Automation.xojo_codeを指定すればOK?)、Custom Plistフォルダーリンクエラー(Kaju-developフォルダー内のCustom Plistフォルダーを指定すればOK?)

  2. Kaju Admin AppとUpdate Test Appに齟齬が
     Update Test App(と、README)ではUpdateInformationの拡張子はhtmlとなっているのですが、Kaju Admin Appではjsonとなっています。
     ファイルの中身はjsonフォーマットなので、ここではjsonに統一しました。(統一されていれば、どちらでも構わないと思われます。)

  3. サーバー側の仕込みが分かりづらい
     Update Test Files (Upload These)フォルダーの内容物がサーバーにアップするものですが、必ずしも全ては必要ありません。
     最小構成は、(当該フォルダーで云えば)Kaju_Update_Test_Mac.zipUpdateInformation.htmlのみです。
    (注:前項の通り、以下の実験では、htmlをjsonに変更)

  4. Update Test Appの機能がリッチ過ぎて、最小限必要なコードの移植が分かりづらい
     READMEにあるものだけで良さそうです。
    (CancelCloseは、Cancelが発生する処理がなければ不要)

  5. マルチプラットホーム対応のため、より複雑になっている
     WindowsとLinuxも含んでいる上に、32bitから64bitに自動アップデートする場合の対応等、Macしか対象にしなければ考えなくていいものも含まれています。
     削除してもいいのですが、そうすると新たなバグを作り込みかねないし、暫く見てると目が慣れてくる(笑)ので、そのままにしておくのが無難そうです。

  6. アップデートが途中で止まる
     これは自作アプリを稼働してから判明したことですが、ダウンロード後にインストールが進まない事態に。
     解決法は以下のサイトにありました。
     参考サイト(2):Kaju ZipShell.Completed Doesn't Fire - Add-Ons - Xojo Programming Forum(Julia Truchsess氏の#12 February 8, 2021, 8:08pmの投稿)

 一度理解してしまえば、READMEにあることがその通りと分かる(よくあるパターン)のですが、ここで改めて整理をしておきます。
(注:以下はKaju Admin Appを用いる方法です。Kaju Admin CLIが使えればビルド時にUpdateInformationファイルも作成できる?ようですが、前述の理由により、未調査)
  1. 対象となるアプリに、Kaju Classesフォルダーをコピー(ドラッグ&ドロップではなく、コピー&ペーストを使え、とのこと)
  2. 対象となるアプリに、Custom Plistフォルダーをドロップ(標準のinfo.plistに追加する方法は、こちらで学んでSparkleの方でも使わせて頂きました。)
  3. AppとWindow1にコンスタント、メソッド、プロパティを追加(README参照)
  4. Kaju Admin App起動し、アプリ毎にバージョン履歴を作成し、保存(以降、アップデート毎に使用する)。RSA public keyをメモ。
  5. 対象アプリのコンスタントに、RSA public keyをコピー
    (ここまでは仕込みの時に一回だけ)

  6. 対象アプリをビルドし、zip圧縮
  7. Kaju Admin App起動し、必要事項を記入の上、UpdateInformationファイル書き出し(以下の画面はBinariesの項)
    S Shot1
  8. zipとUpdateInformationをサーバーにアップロード(別途FTPソフトで実行)

  9. 対象アプリをアップデートしたら、6〜8を繰り返す
 以上を踏まえ、テストアプリを作ってみることにします。仕様は以下の通りとしました。

 Xojoでの実装
【ソースコードのコピー&ペーストについて】
・ソースコード(グレー背景部分の全文)をコピーし、指定のオブジェクトにペーストすると、(新規作成して名前等を個別にコピー&ペーストしなくても)復元されます。
・ペーストはオブジェクトに行って下さい。オブジェクト内のEvent Handlers/Methods/Properties等にペーストしても、うまくいかない場合があります。
・それでもペーストできない場合は、各項目のカッコ内を適用して下さい。
  1. Xojoで新規プロジェクトを作成
  2. 以下をAppにペースト
    Sub Close() Handles Close
      App.UpdateInitiater = Nil
    End Sub
    
  3. 以下をAppにペースト
    Sub Open() Handles Open
      mPrefFolder = SpecialFolder.ApplicationData.Child( "KajuTest1" )
      if not mPrefFolder.Exists then
        mPrefFolder.CreateAsFolder
      end if
    End Sub
    
  4. 以下をAppにペースト
    Public Function PrefFolder() As FolderItem
      return mPrefFolder
    End Function
    
  5. 以下をAppにペースト(できなければPropertyに、Name:mPrefFolder、Type:FolderItem、を追加)
    Private Property mPrefFolder As FolderItem
    
  6. 以下をAppにペースト(できなければPropertyに、Name:UpdateInitiater、Type:Kaju.UpdateInitiater、を追加)
    Public Property UpdateInitiater As Kaju.UpdateInitiater
    
  7. MainMenuBarの、任意のメニューに、メニュー項目(Name:ApplicationUpdate、Super:ApplicationMenuItem、Text:アップデートを確認...)を追加
  8. 以下をWindow1にペースト(できなければConstantsに、Constant Name:kBaseURL、Type:String、を追加)後、Default Valueに<自分のサーバーのアップロード先>をセット
    Public Const kBaseURL as String
    
  9. 以下をWindow1にペースト(できなければConstantsに、Constant Name:kServerPublicKey、Type:String、を追加)後、Default Valueに<Kaju Admin AppでメモしたRSA public key>をコピー
    Private Const kServerPublicKey as String
    
  10. 以下をWindow1にペースト(できなければConstantsに、Constant Name:kUpdateFile、Default Value:UpdateInformation.json、Type:String、を追加)
    Public Const kUpdateFile as String = UpdateInformation.json
    
  11. 以下をWindow1にペースト
    Sub Open() Handles Open
      // Kaju初期化
      InitKaju()
    End Sub
    
  12. 以下をWindow1にペースト(メニューハンドラー)
    Function ApplicationUpdate() As Boolean
      mShowMsg=true
      Checker.ExecuteAsync()
      
      Return True
    End Function
    
  13. 以下をWindow1にペースト
    Private Sub Checker_ExecuteAsyncComplete(sender As Kaju.UpdateChecker)
      #pragma unused sender
      HandlePostCheck
    End Sub
    
  14. 以下をWindow1にペースト
    Private Sub HandlePostCheck()
      if mShowMsg=false then
        return
      end if
      
      select case Checker.Result
      case Kaju.UpdateChecker.ResultType.NoUpdateAvailable
        MessageBox "No updates available"
      end select
    End Sub
    
  15. 以下をWindow1にペースト
    Protected Sub InitKaju()
      // Kaju.UpdateCheckerのインスタンス生成
      dim u as new Kaju.UpdateChecker( App.PrefFolder )
      
      // セットアップ
      Checker = u
      AddHandler Checker.ExecuteAsyncComplete, WeakAddressOf Checker_ExecuteAsyncComplete
      Checker.ServerPublicRSAKey = kServerPublicKey
      Checker.UpdateURL = kBaseURL + kUpdateFile
      
      // 直ちにアップデートチェック
      mShowMsg=false  // メッセージは非表示
      Checker.ExecuteAsync()
    End Sub
    
  16. 以下をWindow1にペースト(できなければPropertyに、Name:Checker、Type:Kaju.UpdateChecker、を追加)
    Public Property Checker As Kaju.UpdateChecker
    
  17. 以下をWindow1にペースト(できなければPropertyに、Name:mShowMsg、Type:Boolean、を追加)
    Protected Property mShowMsg As Boolean
    
  18. Custom Plistフォルダーをドラッグ&ドロップ
  19. Kaju Classesをコピー
  20. Kaju Classes>KajuUpdateWindow>Controls>hsSocket>FileReceived>shZipper.Decompress( file, targetFolder )の上に以下を挿入
    Shell(shZipper).mode = 1 // ### added per Kem 2/8/21
    
     参考サイト(2):Kaju ZipShell.Completed Doesn't Fire - Add-Ons - Xojo Programming Forum(Julia Truchsess氏の#12 February 8, 2021, 8:08pmの投稿)
 ビルドしてサーバーにアップし、バージョンを上げて再度ビルドして実行してみたところ、自動アップデートが機能することを確認しました。
下記テキストの上にマウスポインターを置くと、画像が切り替わります。
アップデート対象が1個アップデート対象が複数個


 おわりに

 Sparkle同様、アップロードしたアプリは、codesign(Authorityを含む)/Notarizeしなくても起動してしまいます。
(codesignとRSA public keyの関係がイマイチよく分かっていないのですが、RSA public keyがcodesignを回避している、という理解で良いのでしょうか?)

 パッケージの形態としては、新規ユーザー向けにはdmgの方が使い勝手がいいので、そうなるとアップデート用のzipとの二本立てになって、煩雑さが増してしまいます。
 Kaju Admin Appをカスタマイズ、または必要部分を移植したアプリを自作する等して、省力化を図った方がよさそうです。

 実装レベルでは、自動アップデートはオプションにするのが作法?のようなので、環境設定等で変更できるようにすることも必要かと思われます。
 あとは日本語化でしょうか。これは、Sparkleが参考になるかもしれません。

 参考サイト(3):Sparkle/Sparkle/ja.lproj at 2.x · sparkle-project/Sparkle · GitHub


 お世話になったサイト

 貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)

 参考サイト(1):GitHub - ktekinay/Kaju: Xojo code for implementing self-updating apps
 参考サイト(2):Kaju ZipShell.Completed Doesn't Fire - Add-Ons - Xojo Programming Forum(Julia Truchsess氏の#12 February 8, 2021, 8:08pmの投稿)
 参考サイト(3):Sparkle/Sparkle/ja.lproj at 2.x · sparkle-project/Sparkle · GitHub


 更新履歴

 2022.03.11 新規作成


[Home]  [MacSoft]  [Donation]  [History]  [Privacy Policy]  [Affiliate Policy]