スマゲ

スマートなゲームづくりを目指して日々精進

UnityでRuntimePermissionを実装する

UnityでRuntimePermissionを実装します

■関連
Android6.0からのPermissionの仕様変更についてのまとめ - スマゲ
AndroidのRuntime Permissionを実装する - スマゲ

■UnityでのRuntimePermissionに関して
Android6.0では特定の権限を利用するアプリ(targetSdkVersion >= 23)を利用する場合ユーザーに対してダイアログで許可を得る必要がある。
Unityの場合、ver5.2.4f1から危険な権限に対して起動時に許可をするかどうかのダイアログを表示するようになっているが、幾つかの問題がある

  • Unity5.2.3以下のバージョンでは使えない

 すでにリリースをしてしまったアプリなど急にUnityのバージョンアップができない場合に対応ができない

  • ゲーム起動時に危険な権限を全て聞く

 AndroidManifestにある危険な権限を起動時に全て聞いてくるので、ユーザーはその権限を何に使うのかわからないまま、許可するかどうかの判断を迫られることになる。場合によってはそのダイアログが出たためにアプリを利用してくれなくなることも考えられる

  • ユーザーの許可、不許可に対して具体的なアクションがとれない

 判断の結果を返す方法がないので、ユーザーの判断から適切なアクションを取れない。

これらの問題があることから好きな時に権限の許可を求めるアラートを出して、その結果に応じたアクションを取れるようにする

~ 実装 ~
結構長いので要点だけ

■ アプリ起動時に権限の許可を求めるダイアログを出さないようにする
ゲーム内のAndroidManifest.xmlに以下の行を追加する。Unityのバージョンが5.2.3f1以下なら必要なし

<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />

■Android Studioで権限をリクエストするコードを書く
リクエストを受け取ったらその権限が許可されているかチェックして、許可されていなかったらリクエストする

public class PermissionManager {
    public static void requestPermission(String permissionName) {
        Activity activity = UnityPlayer.currentActivity;
        if (!hasPermission(permissionName)) {
            activity.requestPermissions(new String[]{permissionName}, 0);
        }
    }

    public static boolean hasPermission(String permissionName){
        Activity activity = UnityPlayer.currentActivity;
        if(Build.VERSION.SDK_INT < 23){
            return true;
        }
        Context context = activity.getApplicationContext();
        return  context.checkCallingOrSelfPermission(permissionName) == PackageManager.PERMISSION_GRANTED;
    }
}

■通知を受け取るためのActivityを作成する
UnityPlayerActivityに権限を許可した時の振る舞いをOverrideしたクラスを作成する。

public class OverrideUnityActivity extends UnityPlayerActivity{

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 0: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    UnityPlayer.UnitySendMessage("UniAndroidPermission", "OnPermit", "");
                } else {
                    UnityPlayer.UnitySendMessage("UniAndroidPermission", "NotPermit", "");
                }
                break;
            }
        }
    }
}

リクエストする機能、それを受け取る機能を作ったらjarにしてUnityに入れる

■Unityで権限をリクエスト/受け取るメソッドを作成する
リクエストを受け取るスクリプトはMonobehaviorにしてシーン内においておく

public static void RequestPremission(AndroidPermission permission, Action onPermit = null, Action notPermit = null){
#if UNITY_EDITOR
    Debug.LogWarning("UniAndroidPermission works only Androud Devices.");
#elif UNITY_ANDROID
    AndroidJavaClass permissionManager = new AndroidJavaClass (PackageClassName);
    permissionManager.CallStatic("requestPermission", GetPermittionStr(permission));
    permitCallBack = onPermit;
    notPermitCallBack = notPermit;
#endif
}

private void OnPermit(){
    if (permitCallBack != null) {
        permitCallBack ();
    }
    ResetCallBacks ();
}

private void NotPermit(){
    if (notPermitCallBack != null) {
        notPermitCallBack ();
    }
    ResetCallBacks ();
}

■OverRideしたActivityを利用できるようにする
AndroidManifestにactivityを追加

<activity android:name="{packageName}.OverrideUnityActivity"
             android:label="@string/app_name"
             android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>

■完成
適切なタイミングでリクエストを送ると確認Windowが出る
f:id:sanukin39:20160322232503p:plain

■Unityプラグイン
整理中...
使い方を以下にまとめました
UnityでRuntimePermissionを利用するプラグイン - スマゲ


■まとめ
必要な権限を必要な時にリクエストでき、さらにユーザーの選択に応じたアクションを行うことができた