Flutterのデスクトップスタンドアロンアプリケーションの自動更新パッケージを作ったfromGithubAssets
はじめに
こんにちは、Rerurate_514と申します。
今回はあるFlutterパッケージを作成しました!
今回作成したパッケージの名前はStandalone_application_updaterです。
名前の通り、デスクトップスタンドアロンアプリケーションの自動更新パッケージになります。
pubにもあります。
install:
flutter pub add standalone_application_updater
概要
まず、このパッケージは[[Github]]のReleaseのアセットに最新版ファイルが存在するかをか確認します。
これのことです。

まず、このタグが現行で動いているアプリのバージョンより高い場合、まずそれを報告します。

そして、そこにファイルが存在している場合にダウンロードを行います。
この場合、.sha256がある場合、整合性チェックもすることができます。
さらに、ダウンロードした後、ファイルを解凍、実行までやってくれるものです。
実際のコード
まず、logを出すか出さないかを決めます。大体はなしでもいいです。
final config = SauConfig(
enableLogging: true,
);
そして、アプリのインスタンスを取得します。
final updater = StandaloneApplicationUpdater.instance;
これがなぜこのような形になっているかというと、OSごとの動作にパッケージが依存する場合、このような形をとることで、パッケージ利用者がOSごとのクラスをインスタンス化する必要がなくなるのです。
そして以下のコードで、Githubのリリースタグが最新のものかどうかを取得できます。
final updateCheckResult = await updater.checkForUpdates(
RepositoryInfo(
owner: "リポジトリオーナー名",
repoName: "リポジトリ名"
),
config
);
ここで帰ってくる値はUpdateCheckResult型です。
このとき、最新のタグがある場合、サブクラスのUpdateCheckAvailableが返ってくるので、それで判定します。
if(updateCheckResult is UpdateCheckAvailable) {
// ...
}
最新版が存在する場合、次のダウンロードフェーズに移れます。
final downloadResult = await updater.downloadUpdate(
updateCheckResult,
config,
savePath: "C:\\Users\\rerur\\Downloads"
);
これはavailable判定ifの中です。
downloadUpdateはUpdateCheckAvailable型しか受け付けません。
そしてこのコードではDownloadUpdateResult型が返ってくるので、それを判定します。
switch(downloadResult) {
case DownloadUpdateSuccess(): {
print("ダウンロードの成功");
}
case DownloadUpdateFailure(): {
print("ダウンロードの失敗");
}
}
ダウンロードは、Stream形式でも行うことができます。
updater.downloadUpdateStream(
updateCheckResult,
config
).listen((downloadResult) {
switch(downloadResult) {
case DownloadUpdateStreamProgress(): {
print("ダウンロードの進行中: ${downloadResult.downloadProgress.percentage}%");
}
case DownloadUpdateStreamSuccess(): {
print("ダウンロードの成功");
}
case DownloadUpdateStreamFailure(): {
print("ダウンロードの失敗");
}
}
});
さらにダウンロードを成功した後、asset内に.sha256ファイルがある場合、それの整合性チェックを行うことができます。
checkSHA256メソッドはDownloadUpdateSuccessまたはDownloadUpdateStreamSuccessしか受け付けません。
この整合性チェックはオプションです、やらないともよいです。
print("ダウンロードの成功");
final isSHA256Valid = await updater.checkSha256(downloadResult, config);
switch(isSHA256Valid) {
case Sha256CheckValid(): {
print("SHA256の整合性が確認できました。");
}
case Sha256CheckInvalid(): {
print("SHA256が一致しません。");
}
case Sha256CheckNotExist(): {
print("SHA256ファイルが指定されたパスにが存在しません。");
}
case Sha256CheckFailed(): {
print("SHA256ファイルのダウンロード中に問題が発生しました。");
}
}
さらにダウンロードしたファイルを自動で実行することもできます。
print("SHA256の整合性が確認できました。");
updater.applyUpdate(
downloadResult,
"zipファイルの中の実行ファイルまでのパス",
config,
isAutoExit: true
);
これで自動アップデートを実行することができます!
さいごに
今回学んだこと
- [[OSごとのインスタンス化を利用者に意識させないパッケージの構築方法]]
- [[Cryptoパッケージの使い方]]
- [[FreezedでResultクラスを作成するのがいい]]
- [[stream]]について
-
yield*は帰ってきたStreamの値をそのまま渡すもの
-
- GithubAPIはめっちゃ高性能
そもそも、このパッケージは自分のデスクトップアプリ用に作成したものなのですが、友達も使う予定があるアプリだったので、自動更新を簡単にしたく、作成しました。
結構いい感じになったのではないのでしょうか。
ちなみに、自動実行はOS依存なのですが、これがwindows版しか作成できていないので、そこのPRが欲しかったり。。。。。
Discussion