ホームページ>開発ツール>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/にアプリ名でフォルダーが作られてアップデートやスキップするとバージョンが記録される、といったあたりでしょうか。
さて、自作アプリへの適用ですが、これが思ったより時間が掛かったのは、主に以下の理由からでした。
一度理解してしまえば、READMEにあることがその通りと分かる(よくあるパターン)のですが、ここで改めて整理をしておきます。
- プロジェクトを立ち上げるとエラーが出る
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?)
- Kaju Admin AppとUpdate Test Appに齟齬が
Update Test App(と、README)ではUpdateInformationの拡張子はhtmlとなっているのですが、Kaju Admin Appではjsonとなっています。
ファイルの中身はjsonフォーマットなので、ここではjsonに統一しました。(統一されていれば、どちらでも構わないと思われます。)
- サーバー側の仕込みが分かりづらい
Update Test Files (Upload These)フォルダーの内容物がサーバーにアップするものですが、必ずしも全ては必要ありません。
最小構成は、(当該フォルダーで云えば)Kaju_Update_Test_Mac.zipとUpdateInformation.htmlのみです。
(注:前項の通り、以下の実験では、htmlをjsonに変更)
- Update Test Appの機能がリッチ過ぎて、最小限必要なコードの移植が分かりづらい
READMEにあるものだけで良さそうです。
(CancelCloseは、Cancelが発生する処理がなければ不要)
- マルチプラットホーム対応のため、より複雑になっている
WindowsとLinuxも含んでいる上に、32bitから64bitに自動アップデートする場合の対応等、Macしか対象にしなければ考えなくていいものも含まれています。
削除してもいいのですが、そうすると新たなバグを作り込みかねないし、暫く見てると目が慣れてくる(笑)ので、そのままにしておくのが無難そうです。
- アップデートが途中で止まる
これは自作アプリを稼働してから判明したことですが、ダウンロード後にインストールが進まない事態に。
解決法は以下のサイトにありました。
参考サイト(2):Kaju ZipShell.Completed Doesn't Fire - Add-Ons - Xojo Programming Forum(Julia Truchsess氏の#12 February 8, 2021, 8:08pmの投稿)
(注:以下はKaju Admin Appを用いる方法です。Kaju Admin CLIが使えればビルド時にUpdateInformationファイルも作成できる?ようですが、前述の理由により、未調査)
以上を踏まえ、テストアプリを作ってみることにします。仕様は以下の通りとしました。
- 対象となるアプリに、Kaju Classesフォルダーをコピー(ドラッグ&ドロップではなく、コピー&ペーストを使え、とのこと)
- 対象となるアプリに、Custom Plistフォルダーをドロップ(標準のinfo.plistに追加する方法は、こちらで学んでSparkleの方でも使わせて頂きました。)
- AppとWindow1にコンスタント、メソッド、プロパティを追加(README参照)
- Kaju Admin App起動し、アプリ毎にバージョン履歴を作成し、保存(以降、アップデート毎に使用する)。RSA public keyをメモ。
- 対象アプリのコンスタントに、RSA public keyをコピー
(ここまでは仕込みの時に一回だけ)
- 対象アプリをビルドし、zip圧縮
- Kaju Admin App起動し、必要事項を記入の上、UpdateInformationファイル書き出し(以下の画面はBinariesの項)
- zipとUpdateInformationをサーバーにアップロード(別途FTPソフトで実行)
- 対象アプリをアップデートしたら、6〜8を繰り返す
- 必要最小限の機能とする。すなわち、
1. アップデートウィンドウの背景は設定しない。(画像のアップロードはなし)
2. 接続はExecuteAsync()のみ。
3. サーバーのリダイレクト/RequiresPaymentは考えない。
4. 32bit/64bit関係は無視。(Macでは必要ない?ため)
- アプリ本体の機能は、メインウィンドウを表示するのみ。(つまり、新規プロジェクトそのまま)
- アップデートの明示的確認用に、メニュー項目を追加する。
- 起動時に、アップデート確認する。
- ExecuteAsync()は終了時にメッセージを表示するが、メニューから確認した時に最新である旨のものだけを表示する。(起動時のチェックでは何も表示しないので、識別用のフラグ用意する)
Xojoでの実装
【ソースコードのコピー&ペーストについて】
・ソースコード(グレー背景部分の全文)をコピーし、指定のオブジェクトにペーストすると、(新規作成して名前等を個別にコピー&ペーストしなくても)復元されます。
・ペーストはオブジェクトに行って下さい。オブジェクト内のEvent Handlers/Methods/Properties等にペーストしても、うまくいかない場合があります。
・それでもペーストできない場合は、各項目のカッコ内を適用して下さい。
ビルドしてサーバーにアップし、バージョンを上げて再度ビルドして実行してみたところ、自動アップデートが機能することを確認しました。
- Xojoで新規プロジェクトを作成
- 以下をAppにペースト
Sub Close() Handles Close App.UpdateInitiater = Nil End Sub
- 以下をAppにペースト
Sub Open() Handles Open mPrefFolder = SpecialFolder.ApplicationData.Child( "KajuTest1" ) if not mPrefFolder.Exists then mPrefFolder.CreateAsFolder end if End Sub
- 以下をAppにペースト
Public Function PrefFolder() As FolderItem return mPrefFolder End Function
- 以下をAppにペースト(できなければPropertyに、Name:mPrefFolder、Type:FolderItem、を追加)
Private Property mPrefFolder As FolderItem
- 以下をAppにペースト(できなければPropertyに、Name:UpdateInitiater、Type:Kaju.UpdateInitiater、を追加)
Public Property UpdateInitiater As Kaju.UpdateInitiater
- MainMenuBarの、任意のメニューに、メニュー項目(Name:ApplicationUpdate、Super:ApplicationMenuItem、Text:アップデートを確認...)を追加
- 以下をWindow1にペースト(できなければConstantsに、Constant Name:kBaseURL、Type:String、を追加)後、Default Valueに<自分のサーバーのアップロード先>をセット
Public Const kBaseURL as String
- 以下をWindow1にペースト(できなければConstantsに、Constant Name:kServerPublicKey、Type:String、を追加)後、Default Valueに<Kaju Admin AppでメモしたRSA public key>をコピー
Private Const kServerPublicKey as String
- 以下をWindow1にペースト(できなければConstantsに、Constant Name:kUpdateFile、Default Value:UpdateInformation.json、Type:String、を追加)
Public Const kUpdateFile as String = UpdateInformation.json
- 以下をWindow1にペースト
Sub Open() Handles Open // Kaju初期化 InitKaju() End Sub
- 以下をWindow1にペースト(メニューハンドラー)
Function ApplicationUpdate() As Boolean mShowMsg=true Checker.ExecuteAsync() Return True End Function
- 以下をWindow1にペースト
Private Sub Checker_ExecuteAsyncComplete(sender As Kaju.UpdateChecker) #pragma unused sender HandlePostCheck End Sub
- 以下を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
- 以下を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
- 以下をWindow1にペースト(できなければPropertyに、Name:Checker、Type:Kaju.UpdateChecker、を追加)
Public Property Checker As Kaju.UpdateChecker
- 以下をWindow1にペースト(できなければPropertyに、Name:mShowMsg、Type:Boolean、を追加)
Protected Property mShowMsg As Boolean
- Custom Plistフォルダーをドラッグ&ドロップ
- Kaju Classesをコピー
- Kaju Classes>KajuUpdateWindow>Controls>hsSocket>FileReceived>shZipper.Decompress( file, targetFolder )の上に以下を挿入
参考サイト(2):Kaju ZipShell.Completed Doesn't Fire - Add-Ons - Xojo Programming Forum(Julia Truchsess氏の#12 February 8, 2021, 8:08pmの投稿)Shell(shZipper).mode = 1 // ### added per Kem 2/8/21
下記テキストの上にマウスポインターを置くと、画像が切り替わります。
アップデート対象が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]