//#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) Console.WriteLine($"{TAG}Awake:"); #endif #if UNITY_ANDROID Input.backButtonLeavesApp = true; // 用终端的背键可以结束应用程序 Initialize(); #endif } //-------------------------------------------------------------------------------- // Java端的事件回调 /** * onStart事件 */ public void OnStartEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnStartEvent:"); #endif } /** * onResume事件 */ public void OnResumeEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnResumeEvent:"); #endif LifecycleEvent?.Invoke(true); } /** * onPause事件 */ public void OnPauseEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnPauseEvent:"); #endif LifecycleEvent?.Invoke(false); } /** * onStop事件 */ public void OnStopEvent() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnStopEvent:"); #endif } /** * 已获得权限 */ public void OnPermissionGrant() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnPermissionGrant:"); #endif grantResult = PermissionGrantResult.PERMISSION_GRANT; isPermissionRequesting = false; } /** * 无法获得权限 */ public void OnPermissionDeny() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnPermissionDeny:"); #endif grantResult = PermissionGrantResult.PERMISSION_DENY; isPermissionRequesting = false; } /** * 设置为无法获取权限而不重新显示权限对话框 */ public void OnPermissionDenyAndNeverAskAgain() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{TAG}OnPermissionDenyAndNeverAskAgain:"); #endif grantResult = PermissionGrantResult.PERMISSION_DENY_AND_NEVER_ASK_AGAIN; isPermissionRequesting = false; } //-------------------------------------------------------------------------------- #if UNITY_ANDROID /** * 初始化插件 */ private void Initialize() { #if (!NDEBUG && DEBUG && ENABLE_LOG) Console.WriteLine($"{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) Console.WriteLine($"{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) Console.WriteLine($"{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) Console.WriteLine($"{TAG}GrantCameraPermission:"); #endif if (CheckAndroidVersion(23)) { // 在Android9以后,UVC设备访问也需要CAMERA权限 yield return GrantPermission(PERMISSION_CAMERA, callback); } else { // 低于Android6不需要权限请求处理 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: 在指定版本之后运行的假:在比指定版本旧的终端上运行 */ 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