anz blog

Unity で Runtime Permission あたりを雑にかいてみた

2018-07-16 #Unity

ざっくりまとめ。

  • 前回の記事でほんとに java がビルドできるのはわかった
  • もう少し実用的なのをってことで、Runtime Permission 周りを書いてみた
  • でもじつはいらなかったよねっていうオチ(笑)

です。

環境

  • Unity v2018.2

ストレージ書き込み権限の許可をもとめる!

WRITE_EXTERNAL_STORAGE 権限の許可をもとめるやつ。 ※ リクエストするだけで結果はひろってません

package xyz.anzfactory.utils;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.Manifest;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;

import com.unity3d.player.UnityPlayer;

public class RuntimePermission {

    private Context mContext;
    private boolean mIsAvailable;

    RuntimePermission() {
        mContext = UnityPlayer.currentActivity;
        mIsAvailable = Build.VERSION.SDK_INT >= 23;
    }

    public boolean isWriteablePermissionGranted() {

        if (!mIsAvailable) {
            return true;    // 旧 OS Version だとインストールした時点で許可されているので true かえす
        }

        return ContextCompat.checkSelfPermission(
            mContext,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        ) == PackageManager.PERMISSION_GRANTED;
    }

    public void requestWritablePermission() {

        if (isWriteablePermissionGranted()) {
            return; // 許可済み!
        }

        // さらに突っ込んで状態チェック
        // 要求したけど断られたのか、まだ一度も要求していないのか
        if (ActivityCompat.shouldShowRequestPermissionRationale(
            (Activity)mContext,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        )) {
            // 一度リクエストしたけど断られている...
            // この場合は、システムがわで再度リクエストできるわけじゃないので、とりまメッセージだすぐらいで勘弁してやる
            Toast.makeText(mContext, "アプリ設定から書き込み権限を許可してください", Toast.LENGTH_SHORT).show();
        } else {
            // まだ一度もリクエストしてないのでする!
            ActivityCompat.requestPermissions(
                (Activity)mContext,
                new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
                9999    // onRequestPermissionsResult受け取る気がないのでてきとー😇
            );
        }
    }
    
}

上にもかいたけど、リクエストするだけなので、これを起動時なんかに雑に呼び出してしまえば...
で、必要な箇所では isWriteablePermissionGranted() とかで確認して挙動切り替えれば、完璧ではないけどそれなりに動くよなぁ〜
という、ざっくりな感じの作りです。

でも、その感じでいいならわざわざ書く必要ない

というのも、Unity の場合許可が必要な権限が Manifest にかかれていた場合、
アプリ起動時に自動で(何もしなくても)権限を求めるリクエストなげてくれるのです(笑)
自分で java なんぞ書かなくても起動時でいいならやってくれるというわけ...
(確認してみよーって動かしたときに気づいた...😇)

ってことで、アプリ起動時じゃなくてボタンタップとかで動かしてみる

この確認だとリクエスト投げっぱなしで、結果はしらん!状態なので...
上記コードを無理やりボタンタップとかに適用する場合、

  • ボタンタップ時に isWriteablePermissionGranted() で確認
    • OK ならその続きの処理を...。
    • NG なら requestWritablePermission() でリクエスト
      • 結果はしらんので、ユーザが再度ボタンタップすることで正常処理へ...

っていう、ユーザに2度タップさせることで一応いける。(イケてないけど)
コード的にはこんな感じ

public void OnClick()
{
    var permissionRequestor = new AndroidJavaObject("xyz.anzfactory.utils.RuntimePermission");

    if (permissionRequestor.Call<bool>("isWriteablePermissionGranted")) {
        // 保存とかそこらの処理?
    } else {
        permissionRequestor.Call("requestWritablePermission");
    }
}

ちなみに、Unityさんがアプ起動時に勝手に(?)許可リクエストなげてくれるやつを無効化するには、
Mannifest に
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" /> を追記するとできます

request_writable_permission

ちゃんとやろうとおもったら、
UnityPlayerActivity なんかのサブクラスをつくって、ソレを起動Activityとして指定して...
で、 onRequestPermissionsResult() をちゃんと実装して結果に応じたメッセージを Unity 側へ投げるっていう感じですかね。
それやっておくと、ユーザが2度タップで確認するみたいなのがなくなります(笑)

権限許可リクエストは、Unityさんの自動でやるやつにまかせて、
その許可されてるかどうかのチェックを自分で java で書いて呼び出す...
ってのが、ここら権限周りの最も楽で簡単なやり方になるかもですね。
チェックするだけなら1メソッドですもんね


やってみて...
やっぱり Unity だけで完結してかけるっていうのは良いですね!
ネイティブ連携かくとなるといままではやっぱり jar ファイルだのつくるのかったりぃぃとかってなりがちでしたからね

ってか、アプリ起動時に自動的にリクエストしてくれるってことは...
投げっぱなしでいいなら実は Unity 側でなにか API 用意されているのでは!?っていう気がしなくもないが、、どうなんだろ
リファレンスをざっくりぱぱーっとみたかんじ無さげだが...参考にのっけたリンクにそんな記述がないからないのかな🤔

参考

Android マニフェスト - Unity マニュアル
ここの Android 6.0 (Marshmallow) のランタイムパーミッション っていう項目に SkipPermissionsDialog の記述があります