Unityで実機上のアプリバージョンを取得する (iOS/Android)
Unityで実機上のアプリバージョンを取得する (iOS/Android)
こんにちは、Nobollelエンジニアの古屋です。今回は、Unity iOS/Android実機でバージョンを取得する方法を紹介します。
一応、アプリバージョンはApplication.version
から取得できます。
Debug.Log("version=" + Application.version);
しかし、これは表示用のバージョンで、厳密なバイナリバージョン (Androidならバージョンコード) が別にあります。ログにバージョンを乗せたいときなど厳密なバージョンの方を知りたいことも多いです。この記事ではこれらを実行時に取得する方法について書いていきます。
iOSのビルド番号を取得する
そもそも「ビルド番号」というのは、Unity上で設定するこれ↓
もしくはXcode上のこれ↓のことです。
(正式名称がよくわかりませんが、Unityのエディタスクリプトのプロパティ名がbuildNumberなので、便宜上ビルド番号と呼んでいます)
「Version」がApp Store上に表示されるバージョンなのに対して、「Build」はアップロードする各バイナリのユニークなバージョンです。たとえば、表示上のバージョンを変えずにバイナリをストアに再アップロードする場合は、Buildの数字を上げる必要があります。
ビルド番号の取得には、ネイティブコードの実装が必要です:
IOSVersion.mm (Plugins/iOS以下に配置)
extern "C" { char *GetBundleVersion() { NSString *bundleVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; const char *s = [bundleVersion UTF8String]; return strcpy((char *)malloc(strlen(s) + 1), s); } }
[NSBundle mainBundle]
のinfoDictionary
からバージョン情報を取り出して返すだけのネイティブコードです。CFBundleVersionというキーがビルド番号に該当します。
プラグインが返す文字列はヒープ上に確保されている必要がある (ここのiOS Tipsを参照) ので、mallocしたポインタにstrcpyして返しています。
次はC#側のコードです:
IOSVersion.cs
#if UNITY_IOS using System.Runtime.InteropServices; #endif #if UNITY_EDITOR using UnityEditor; #endif public static class IOSVersion { public static string GetBuildNumber() { #if UNITY_EDITOR return PlayerSettings.iOS.buildNumber; #elif UNITY_IOS return GetBundleVersion(); #else return null; #endif } #if UNITY_IOS [DllImport("__Internal")] static extern string GetBundleVersion(); #endif }
C#側では、さきほどのネイティブの関数2つをラップしているだけです。エディタ上ではプラグインが動作しないのでPlayerSettingsから値を取得して返し、iOS以外のプラットフォームではnullを返します。
Androidのバージョンコードを取得する
Androidでは、iOSのビルド番号に相当するものとしてバージョンコードがあります。こちらはネイティブコードを書かなくても、AndroidJavaObjectを使って実装できます。
AncroidVersion.cs
#if UNITY_ANDROID using UnityEngine; #endif #if UNITY_EDITOR using UnityEditor; #endif public static class AndroidVersion { public static int GetVersionCode() { #if UNITY_EDITOR return PlayerSettings.Android.bundleVersionCode; #elif UNITY_ANDROID using (var packageInfo = GetPackageInfo()) { return packageInfo.Get<int>("versionCode"); } #else return 0; #endif } #if UNITY_ANDROID static AndroidJavaObject GetPackageInfo() { using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) using (var context = currentActivity.Call<AndroidJavaObject>("getApplicationContext")) using (var packageManager = context.Call<AndroidJavaObject>("getPackageManager")) using (var packageManagerClass = new AndroidJavaClass("android.content.pm.PackageManager")) { string packageName = context.Call<string>("getPackageName"); int activities = packageManagerClass.GetStatic<int>("GET_ACTIVITIES"); return packageManager.Call<AndroidJavaObject>("getPackageInfo", packageName, activities); } } #endif }
GetPackageInfoは見た目ごちゃごちゃしていますが、アクティビティからPackageManagerを取ってきてgetPackageInfoしているだけです。戻り値のPackageInfoクラスがバージョン情報を持っており、そこからversionCodeを取得します。