はじめに
Mauiのアプリ開発が完了しました。
開発終盤に開発した機能に、
Androidアプリにて現在のアプリのバージョンがストアのバージョンよりも古い場合、
古いバージョンは使用して欲しくないのでアプリを終了し、ユーザに更新を促す処理があります。
処理は以下のような流れで、
0. アプリを起動
1. ストアのアプリバージョンを取得
2. 現在のバージョンと比較
3. 現在のバージョンが古ければ、ストアページに遷移してアプリを終了
この内の1の工程におけるGooglePlayストアからアプリのバージョンを取得する処理についての共有記事となります。
重要なことなので先に言っておきますと、
デバイスによりバージョンが異なるアプリ(大手のアプリの多く、YouTubeやGoogleChromeなどなど)の場合は取得できません。
先行事例
iPhoneのAppStoreアプリの場合、iTunesAPIによりバージョンが取得できるので、
GooglePlayストアにも該当するAPIがないか調べてみたのですが見つからず、
代わりにストアページのhtmlを取得してパースする方法が見つかりました。
Google Playにあるアプリのバージョンを取得したい – すなばいじり
これで解決かと思い、ストアページのhtmlを覗いてみたところ、
どうも記事の投稿時点(6年前)と今とでは形式が異なるようで、
パースする正規表現に関しては考え直す必要がありました。
手法
考え直してC#にて実装した方法が以下のやりかたです。
/// <summary> ストア上のアプリバージョンを取得します。 </summary>
public async Task GetStoreAppVersion(string appPackageId) {
// 毎回HttpClientのインスタンスを作り直すのは良くないそうですがサンプルコードなので
using var httpClient = new HttpClient();
// ストアページのhtmlをhttpで取得してバージョンをパースする
var playStoreUrl = $"https://play.google.com/store/apps/details?id={appPackageId}";
// Getリクエストを投げて、結果のContentをstringで取得する処理(実装省略
var content = await GetContent(httpClient, playStoreUrl);
// バージョン部 (?\d+\.\d[\d\.]*): 数字1個以上 ドット1個 数字ないしドット0個以上
// 一致例:<script class="ds:0" nonce="EssQcMMS9rrE4BPTbLD7PA">AF_initDataCallback( ...... ],[[[1.0.0]],[ ...... );</script>
var match = Regex.Match(content, @"<script class=""ds:\d+"" nonce=""[^""]+"">AF_initDataCallback\(.+?\[\[\[""(?\d+\.\d[\d\.]*)""\]\].+?\);</script>");
if (match.Success.Not()) return null;
var ver = match.Groups["ver"].Value;
return new Version(ver);
}
この実装により、数字とドットからなる一般的な記法のバージョンをパース可能です。
※バージョンが特殊な記法の場合はバージョン部の正規表現を変える必要があります。
また、バージョンがデバイスにより異なる場合も取得できません。
一般向けの大手のアプリはデバイスにより異なる場合が多く取得できないので、
残念ながら汎用性はないです。
※正規表現文字列は変数化しようかと思ったのですが、
VSがいい感じに見やすく色分けしてくれたのでそのままにしました
取得例
例として先行事例での対象アプリ、Nintendo Switch Onlineから取得してみます。
引数appPackageIdに”com.nintendo.znca”を与えてGetStoreAppVersionを呼ぶと、
html内の以下の記述にマッチし、バージョン2.10.1が取得できます。
<script class=”ds:0″ nonce=”EssQcMMS9rrE4BPTbLD7PA”>AF_initDataCallback( …… ],[[["2.10.1"]],[ …… );</script>
ストアのページでバージョンを確認してみると実際に2.10.1と表示されているので、
正しくバージョンを取得できていることがわかります。
(この表示から取得するので、ここに”デバイスにより異なります”と記載されている場合は取得できません。)
おわりに
アプリの更新を促す処理の実装のために、
GooglePlayストアページのhtmlからアプリのバージョンをパースして取得する方法の
令和最新版(24/8/16現在)についての共有でした。
この方法はデバイスによりバージョンの異なるアプリは取得できませんが、
自社で開発するアプリならバージョンを統一できるので問題なく使用できます。
今後は工場向けのモバイルアプリも増えていくかと思いますので、
その開発の際にも役に立つ機能です。
ちなみに更新を促す機能を実装する手段としては他に、
Google Play CoreライブラリのIn-app updates機能を使用して
バージョンチェックから更新処理までの一連の流れを
ライブラリの機能で実装する方法もあるようでした。
おそらくそちらが主流だと思われたのですが、
以下の理由などにより泣く泣く不採用(バージョン取得の方を採用)としました。
・ライブラリの調査にかかる時間が不透明
・デバッグしながらの開発ができず開発コストが増える
(GooglePlayConsoleにリリースビルドしてアップロードしないとおそらくテストできないため)
・iPhoneアプリにて既にitunesAPIでバージョン取得・自前で比較・ストアに遷移まで行っており、
バージョン取得の方法であれば実装の共通化が可能でその分開発コストが下がる
今の方法だとストアのhtmlの形式が変更される度に
バージョンをパースする部分をメンテしないといけないので、
あまり変更されないと、、、良いな、、、とGoogle本社の方角に向けてお祈りしております。
以上です。