/****************************************************************************
* 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);
}
}
}