AndroidUtils.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. //#define ENABLE_LOG
  2. /*
  3. * Copyright (c) 2014 - 2022 t_saki@serenegiant.com
  4. */
  5. using System;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using UnityEngine;
  10. #if UNITY_ANDROID
  11. #if UNITY_2018_3_OR_NEWER
  12. using UnityEngine.Android;
  13. #endif
  14. #endif
  15. namespace Serenegiant
  16. {
  17. public class AndroidUtils : MonoBehaviour
  18. {
  19. public const string FQCN_UNITY_PLAYER = "com.unity3d.player.UnityPlayer";
  20. public const string PERMISSION_CAMERA = "android.permission.CAMERA";
  21. public enum PermissionGrantResult
  22. {
  23. PERMISSION_GRANT = 0,
  24. PERMISSION_DENY = -1,
  25. PERMISSION_DENY_AND_NEVER_ASK_AGAIN = -2
  26. }
  27. private const string TAG = "AndroidUtils#";
  28. private const string FQCN_PLUGIN = "com.serenegiant.androidutils.AndroidUtils";
  29. //--------------------------------------------------------------------------------
  30. /**
  31. * ライフサイクルイベント用のデリゲーター
  32. * @param resumed true: onResume, false: onPause
  33. */
  34. public delegate void LifecycleEventHandler(bool resumed);
  35. /***
  36. * GrantPermissionでパーミッションを要求したときのコールバック用delegateer
  37. * @param permission
  38. * @param grantResult 0:grant, -1:deny, -2:denyAndNeverAskAgain
  39. */
  40. public delegate void OnPermission(string permission, PermissionGrantResult result);
  41. //--------------------------------------------------------------------------------
  42. /**
  43. * パーミッション要求時のタイムアウト
  44. */
  45. public static float PermissionTimeoutSecs = 30;
  46. public event LifecycleEventHandler LifecycleEvent;
  47. public static bool isPermissionRequesting;
  48. private static PermissionGrantResult grantResult;
  49. void Awake()
  50. {
  51. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  52. Console.WriteLine($"{TAG}Awake:");
  53. #endif
  54. #if UNITY_ANDROID
  55. Input.backButtonLeavesApp = true; // 端末のバックキーでアプリを終了できるようにする
  56. Initialize();
  57. #endif
  58. }
  59. //--------------------------------------------------------------------------------
  60. // Java側からのイベントコールバック
  61. /**
  62. * onStartイベント
  63. */
  64. public void OnStartEvent()
  65. {
  66. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  67. Console.WriteLine($"{TAG}OnStartEvent:");
  68. #endif
  69. }
  70. /**
  71. * onResumeイベント
  72. */
  73. public void OnResumeEvent()
  74. {
  75. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  76. Console.WriteLine($"{TAG}OnResumeEvent:");
  77. #endif
  78. LifecycleEvent?.Invoke(true);
  79. }
  80. /**
  81. * onPauseイベント
  82. */
  83. public void OnPauseEvent()
  84. {
  85. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  86. Console.WriteLine($"{TAG}OnPauseEvent:");
  87. #endif
  88. LifecycleEvent?.Invoke(false);
  89. }
  90. /**
  91. * onStopイベント
  92. */
  93. public void OnStopEvent()
  94. {
  95. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  96. Console.WriteLine($"{TAG}OnStopEvent:");
  97. #endif
  98. }
  99. /**
  100. * パーミッションを取得できた
  101. */
  102. public void OnPermissionGrant()
  103. {
  104. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  105. Console.WriteLine($"{TAG}OnPermissionGrant:");
  106. #endif
  107. grantResult = PermissionGrantResult.PERMISSION_GRANT;
  108. isPermissionRequesting = false;
  109. }
  110. /**
  111. * パーミッションを取得できなかった
  112. */
  113. public void OnPermissionDeny()
  114. {
  115. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  116. Console.WriteLine($"{TAG}OnPermissionDeny:");
  117. #endif
  118. grantResult = PermissionGrantResult.PERMISSION_DENY;
  119. isPermissionRequesting = false;
  120. }
  121. /**
  122. * パーミッションを取得できずパーミッションダイアログを再び表示しないように設定された
  123. */
  124. public void OnPermissionDenyAndNeverAskAgain()
  125. {
  126. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  127. Console.WriteLine($"{TAG}OnPermissionDenyAndNeverAskAgain:");
  128. #endif
  129. grantResult = PermissionGrantResult.PERMISSION_DENY_AND_NEVER_ASK_AGAIN;
  130. isPermissionRequesting = false;
  131. }
  132. //--------------------------------------------------------------------------------
  133. #if UNITY_ANDROID
  134. /**
  135. * プラグインの初期化実行
  136. */
  137. private void Initialize()
  138. {
  139. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  140. Console.WriteLine($"{TAG}Initialize:{gameObject.name}");
  141. #endif
  142. using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
  143. {
  144. clazz.CallStatic("initialize",
  145. AndroidUtils.GetCurrentActivity(), gameObject.name);
  146. }
  147. }
  148. /**
  149. * 指定したパーミッションを保持しているかどうかを取得
  150. * @param permission
  151. * @param 指定したパーミッションを保持している
  152. */
  153. public static bool HasPermission(string permission)
  154. {
  155. using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
  156. {
  157. return clazz.CallStatic<bool>("hasPermission",
  158. AndroidUtils.GetCurrentActivity(), permission);
  159. }
  160. }
  161. /**
  162. * 指定したパーミッションの説明を表示する必要があるかどうかを取得
  163. * @param permission
  164. * @param 指定したパーミッションの説明を表示する必要がある
  165. */
  166. public static bool ShouldShowRequestPermissionRationale(string permission)
  167. {
  168. using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
  169. {
  170. return clazz.CallStatic<bool>("shouldShowRequestPermissionRationale",
  171. AndroidUtils.GetCurrentActivity(), permission);
  172. }
  173. }
  174. /**
  175. * パーミッション要求
  176. * こっちはJava側でRationaleの処理等を行わない
  177. * @param permission
  178. * @param callback
  179. */
  180. public static IEnumerator RequestPermission(string permission, OnPermission callback)
  181. {
  182. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  183. Console.WriteLine($"{TAG}GrantPermission:{permission}");
  184. #endif
  185. if (!HasPermission(permission))
  186. {
  187. grantResult = PermissionGrantResult.PERMISSION_DENY;
  188. isPermissionRequesting = true;
  189. using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
  190. {
  191. clazz.CallStatic("requestPermission",
  192. AndroidUtils.GetCurrentActivity(), permission);
  193. }
  194. float timeElapsed = 0;
  195. while (isPermissionRequesting)
  196. {
  197. if ((PermissionTimeoutSecs > 0) && (timeElapsed > PermissionTimeoutSecs))
  198. {
  199. isPermissionRequesting = false;
  200. yield break;
  201. }
  202. timeElapsed += Time.deltaTime;
  203. yield return null;
  204. }
  205. callback(permission, grantResult);
  206. }
  207. else
  208. {
  209. callback(permission, PermissionGrantResult.PERMISSION_GRANT);
  210. }
  211. yield break;
  212. }
  213. /**
  214. * パーミッション要求
  215. * こっちはJava側でRationaleの処理等を行う
  216. * @param permission
  217. * @param callback
  218. */
  219. public static IEnumerator GrantPermission(string permission, OnPermission callback)
  220. {
  221. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  222. Console.WriteLine($"{TAG}GrantPermission:{permission}");
  223. #endif
  224. if (!HasPermission(permission))
  225. {
  226. grantResult = PermissionGrantResult.PERMISSION_DENY;
  227. isPermissionRequesting = true;
  228. using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
  229. {
  230. clazz.CallStatic("grantPermission",
  231. AndroidUtils.GetCurrentActivity(), permission);
  232. }
  233. float timeElapsed = 0;
  234. while (isPermissionRequesting)
  235. {
  236. if ((PermissionTimeoutSecs > 0) && (timeElapsed > PermissionTimeoutSecs))
  237. {
  238. isPermissionRequesting = false;
  239. yield break;
  240. }
  241. timeElapsed += Time.deltaTime;
  242. yield return null;
  243. }
  244. callback(permission, grantResult);
  245. }
  246. else
  247. {
  248. callback(permission, PermissionGrantResult.PERMISSION_GRANT);
  249. }
  250. yield break;
  251. }
  252. /**
  253. * カメラパーミッションを要求
  254. * @param callback
  255. */
  256. public static IEnumerator GrantCameraPermission(OnPermission callback)
  257. {
  258. #if (!NDEBUG && DEBUG && ENABLE_LOG)
  259. Console.WriteLine($"{TAG}GrantCameraPermission:");
  260. #endif
  261. if (CheckAndroidVersion(23))
  262. {
  263. // Android9以降ではUVC機器アクセスにもCAMERAパーミッションが必要
  264. yield return GrantPermission(PERMISSION_CAMERA, callback);
  265. }
  266. else
  267. {
  268. // Android 6 未満ではパーミッション要求処理は不要
  269. callback(PERMISSION_CAMERA, PermissionGrantResult.PERMISSION_GRANT);
  270. }
  271. yield break;
  272. }
  273. //================================================================================
  274. /**
  275. * UnityPlayerActivityを取得
  276. */
  277. public static AndroidJavaObject GetCurrentActivity()
  278. {
  279. using (AndroidJavaClass playerClass = new AndroidJavaClass(FQCN_UNITY_PLAYER))
  280. {
  281. return playerClass.GetStatic<AndroidJavaObject>("currentActivity");
  282. }
  283. }
  284. /**
  285. * 指定したバージョン以降かどうかを確認
  286. * @param apiLevel
  287. * @return true: 指定したバージョン以降で実行されている, false: 指定したバージョンよりも古い端末で実行されている
  288. */
  289. public static bool CheckAndroidVersion(int apiLevel)
  290. {
  291. using (var VERSION = new AndroidJavaClass("android.os.Build$VERSION"))
  292. {
  293. return VERSION.GetStatic<int>("SDK_INT") >= apiLevel;
  294. }
  295. }
  296. } // class AndroidUtils
  297. } // namespace Serenegiant
  298. #endif // #if UNITY_ANDROID