/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal { using System; using UnityEngine; /// Manages Android permissions for the Unity application. public class NRAndroidPermissionsManager : AndroidJavaProxy, IAndroidPermissionsCheck { /// The instance. private static NRAndroidPermissionsManager _instance; /// The activity. private static AndroidJavaObject _activity; /// The permission service. private static AndroidJavaObject _permissionService; /// The current request. private static AsyncTask _currentRequest = null; /// The action on permissions request finished. private static Action _onPermissionsRequestFinished; /// The current screen capture request. private static AsyncTask _curScreenCaptureRequest = null; /// The action on screen capture request finished. private static Action _onScreenCaptureRequestFinished; private static AndroidJavaObject _mediaProjection; /// Constructs a new AndroidPermissionsManager. public NRAndroidPermissionsManager() : base( "ai.nreal.sdk.UnityAndroidPermissions$IPermissionRequestResult") { } /// Checks if an Android permission is granted to the application. /// The full name of the Android permission to check (e.g. /// android.permission.CAMERA). /// /// true if permissionName is granted to the application, otherwise /// false. public static bool IsPermissionGranted(string permissionName) { if (Application.platform != RuntimePlatform.Android) { return true; } return GetPermissionsService().Call( "IsPermissionGranted", GetUnityActivity(), permissionName); } /// Requests an Android permission from the user. /// The permission to be requested (e.g. android.permission.CAMERA). /// /// An asynchronous task that completes when the user has accepted or rejected the requested /// permission and yields a that summarizes the /// result. If this method is called when another permissions request is pending, null /// will be returned instead. public static AsyncTask RequestPermission( string permissionName) { if (NRAndroidPermissionsManager.IsPermissionGranted(permissionName)) { return new AsyncTask( new AndroidPermissionsRequestResult( new string[] { permissionName }, new bool[] { true })); } if (_currentRequest != null) { NRDebugger.Error("Attempted to make simultaneous Android permissions requests."); return null; } _currentRequest = new AsyncTask(out _onPermissionsRequestFinished); GetPermissionsService().Call("RequestPermissionAsync", GetUnityActivity(), new[] { permissionName }, GetInstance()); return _currentRequest; } /// Requests an Android permission from the user. /// The permission to be requested (e.g. android.permission.CAMERA). /// /// An asynchronous task that completes when the user has accepted or rejected the requested /// permission and yields a that summarizes the /// result. If this method is called when another permissions request is pending, null /// will be returned instead. public AsyncTask RequestAndroidPermission( string permissionName) { return RequestPermission(permissionName); } /// Callback fired when a permission is granted. /// The name of the permission that was granted. public virtual void OnPermissionGranted(string permissionName) { OnPermissionResult(permissionName, true); } /// Callback fired when a permission is denied. /// The name of the permission that was denied. public virtual void OnPermissionDenied(string permissionName) { OnPermissionResult(permissionName, false); } /// Gets the instance. /// The instance. public static NRAndroidPermissionsManager GetInstance() { if (_instance == null) { _instance = new NRAndroidPermissionsManager(); } return _instance; } /// Gets unity activity. /// The unity activity. private static AndroidJavaObject GetUnityActivity() { if (_activity == null) { AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); _activity = unityPlayer.GetStatic("currentActivity"); } return _activity; } /// Gets permissions service. /// The permissions service. private static AndroidJavaObject GetPermissionsService() { if (_permissionService == null) { _permissionService = new AndroidJavaObject("ai.nreal.sdk.UnityAndroidPermissions"); } return _permissionService; } /// Callback fired on an Android permission result. /// The name of the permission. /// If permission is granted or not. private void OnPermissionResult(string permissionName, bool granted) { if (_onPermissionsRequestFinished == null) { Debug.LogErrorFormat( "AndroidPermissionsManager received an unexpected permissions result {0}", permissionName); return; } // Cache completion method and reset request state. var onRequestFinished = _onPermissionsRequestFinished; _currentRequest = null; _onPermissionsRequestFinished = null; onRequestFinished(new AndroidPermissionsRequestResult(new string[] { permissionName }, new bool[] { granted })); } /// Requests Android screen capture from the user. /// /// An asynchronous task that completes when the user has approved or rejected the requested /// ScreenCapture and yields a that store the Android MediaProjection /// result. If this method is called when another screen capture request is pending, null /// will be returned instead. public AsyncTask RequestScreenCapture() { Debug.LogFormat("AndroidPermissionsManager RequestScreenCapture: cache={0}", _mediaProjection != null); if (_mediaProjection != null) { return new AsyncTask(_mediaProjection); } if (_curScreenCaptureRequest != null) { NRDebugger.Error("Attempted to make simultaneous Android permissions requests."); return null; } _curScreenCaptureRequest = new AsyncTask(out _onScreenCaptureRequestFinished); GetPermissionsService().Call("RequestScreenCaptureAsync", GetUnityActivity(), GetInstance()); return _curScreenCaptureRequest; } /// Callback is fired when screen capture is granted. public virtual void OnScreenCaptureGranted(AndroidJavaObject mediaProjection) { OnScreenCaptureResult(true, mediaProjection); } /// Callback is fired when screen capture is denied. public virtual void OnScreenCaptureDenied() { OnScreenCaptureResult(false, null); } /// Callback fired on an Android screen capture result. /// If screen capture is granted or not. /// The android MediaProjection object. private void OnScreenCaptureResult(bool granted, AndroidJavaObject mediaProjection) { Debug.LogFormat("AndroidPermissionsManager OnScreenCaptureGranted: granted={0}, mediaProjection={1}", granted, mediaProjection!=null); if (_onScreenCaptureRequestFinished == null) { Debug.LogError("AndroidPermissionsManager received an unexpected screencapture result"); return; } // Cache completion method and reset request state. var onRequestFinished = _onScreenCaptureRequestFinished; _curScreenCaptureRequest = null; _onScreenCaptureRequestFinished = null; if (granted) _mediaProjection = mediaProjection; onRequestFinished(mediaProjection); } } }