//#define ENABLE_LOG /* * Copyright (c) 2014 - 2022 t_saki@serenegiant.com */ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using UnityEngine; #if UNITY_ANDROID #if UNITY_2018_3_OR_NEWER using UnityEngine.Android; #endif #endif namespace Serenegiant { public class AndroidUtils : MonoBehaviour { public const string FQCN_UNITY_PLAYER = "com.unity3d.player.UnityPlayer"; public const string PERMISSION_CAMERA = "android.permission.CAMERA"; public enum PermissionGrantResult { PERMISSION_GRANT = 0, PERMISSION_DENY = -1, PERMISSION_DENY_AND_NEVER_ASK_AGAIN = -2 } private const string TAG = "AndroidUtils#"; private const string FQCN_PLUGIN = "com.serenegiant.androidutils.AndroidUtils"; //-------------------------------------------------------------------------------- /** * ライフサイクルイベント用のデリゲーター * @param resumed true: onResume, false: onPause */ public delegate void LifecycleEventHandler(bool resumed); /*** * GrantPermissionでパーミッションを要求したときのコールバック用delegateer * @param permission * @param grantResult 0:grant, -1:deny, -2:denyAndNeverAskAgain */ public delegate void OnPermission(string permission, PermissionGrantResult result); //-------------------------------------------------------------------------------- /** * パーミッション要求時のタイムアウト */ public static float PermissionTimeoutSecs = 30; public event LifecycleEventHandler LifecycleEvent; public static bool isPermissionRequesting; private static PermissionGrantResult grantResult; void Awake() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}Awake:"); #endif #if UNITY_ANDROID Input.backButtonLeavesApp = true; // 端末のバックキーでアプリを終了できるようにする Initialize(); #endif } //-------------------------------------------------------------------------------- // Java側からのイベントコールバック /** * onStartイベント */ public void OnStartEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnStartEvent:"); #endif } /** * onResumeイベント */ public void OnResumeEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnResumeEvent:"); #endif LifecycleEvent?.Invoke(true); } /** * onPauseイベント */ public void OnPauseEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnPauseEvent:"); #endif LifecycleEvent?.Invoke(false); } /** * onStopイベント */ public void OnStopEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnStopEvent:"); #endif } /** * パーミッションを取得できた */ public void OnPermissionGrant() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnPermissionGrant:"); #endif grantResult = PermissionGrantResult.PERMISSION_GRANT; isPermissionRequesting = false; } /** * パーミッションを取得できなかった */ public void OnPermissionDeny() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnPermissionDeny:"); #endif grantResult = PermissionGrantResult.PERMISSION_DENY; isPermissionRequesting = false; } /** * パーミッションを取得できずパーミッションダイアログを再び表示しないように設定された */ public void OnPermissionDenyAndNeverAskAgain() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}OnPermissionDenyAndNeverAskAgain:"); #endif grantResult = PermissionGrantResult.PERMISSION_DENY_AND_NEVER_ASK_AGAIN; isPermissionRequesting = false; } //-------------------------------------------------------------------------------- #if UNITY_ANDROID /** * プラグインの初期化実行 */ private void Initialize() { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}Initialize:{gameObject.name}"); #endif using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN)) { clazz.CallStatic("initialize", AndroidUtils.GetCurrentActivity(), gameObject.name); } } /** * 指定したパーミッションを保持しているかどうかを取得 * @param permission * @param 指定したパーミッションを保持している */ public static bool HasPermission(string permission) { using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN)) { return clazz.CallStatic("hasPermission", AndroidUtils.GetCurrentActivity(), permission); } } /** * 指定したパーミッションの説明を表示する必要があるかどうかを取得 * @param permission * @param 指定したパーミッションの説明を表示する必要がある */ public static bool ShouldShowRequestPermissionRationale(string permission) { using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN)) { return clazz.CallStatic("shouldShowRequestPermissionRationale", AndroidUtils.GetCurrentActivity(), permission); } } /** * パーミッション要求 * こっちはJava側でRationaleの処理等を行わない * @param permission * @param callback */ public static IEnumerator RequestPermission(string permission, OnPermission callback) { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}GrantPermission:{permission}"); #endif if (!HasPermission(permission)) { grantResult = PermissionGrantResult.PERMISSION_DENY; isPermissionRequesting = true; using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN)) { clazz.CallStatic("requestPermission", AndroidUtils.GetCurrentActivity(), permission); } float timeElapsed = 0; while (isPermissionRequesting) { if ((PermissionTimeoutSecs > 0) && (timeElapsed > PermissionTimeoutSecs)) { isPermissionRequesting = false; yield break; } timeElapsed += Time.deltaTime; yield return null; } callback(permission, grantResult); } else { callback(permission, PermissionGrantResult.PERMISSION_GRANT); } yield break; } /** * パーミッション要求 * こっちはJava側でRationaleの処理等を行う * @param permission * @param callback */ public static IEnumerator GrantPermission(string permission, OnPermission callback) { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}GrantPermission:{permission}"); #endif if (!HasPermission(permission)) { grantResult = PermissionGrantResult.PERMISSION_DENY; isPermissionRequesting = true; using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN)) { clazz.CallStatic("grantPermission", AndroidUtils.GetCurrentActivity(), permission); } float timeElapsed = 0; while (isPermissionRequesting) { if ((PermissionTimeoutSecs > 0) && (timeElapsed > PermissionTimeoutSecs)) { isPermissionRequesting = false; yield break; } timeElapsed += Time.deltaTime; yield return null; } callback(permission, grantResult); } else { callback(permission, PermissionGrantResult.PERMISSION_GRANT); } yield break; } /** * カメラパーミッションを要求 * @param callback */ public static IEnumerator GrantCameraPermission(OnPermission callback) { #if (!NDEBUG && DEBUG && ENABLE_LOG) LogPrint.Log($"{TAG}GrantCameraPermission:"); #endif if (CheckAndroidVersion(23)) { // Android9以降ではUVC機器アクセスにもCAMERAパーミッションが必要 yield return GrantPermission(PERMISSION_CAMERA, callback); } else { // Android 6 未満ではパーミッション要求処理は不要 callback(PERMISSION_CAMERA, PermissionGrantResult.PERMISSION_GRANT); } yield break; } //================================================================================ /** * UnityPlayerActivityを取得 */ public static AndroidJavaObject GetCurrentActivity() { using (AndroidJavaClass playerClass = new AndroidJavaClass(FQCN_UNITY_PLAYER)) { return playerClass.GetStatic("currentActivity"); } } /** * 指定したバージョン以降かどうかを確認 * @param apiLevel * @return true: 指定したバージョン以降で実行されている, false: 指定したバージョンよりも古い端末で実行されている */ public static bool CheckAndroidVersion(int apiLevel) { using (var VERSION = new AndroidJavaClass("android.os.Build$VERSION")) { return VERSION.GetStatic("SDK_INT") >= apiLevel; } } } // class AndroidUtils } // namespace Serenegiant #endif // #if UNITY_ANDROID