码字不易,转载请注明出处:
https://blog.csdn.net/newchenxf/article/details/119956445
在 Android 6(API 级别 23)及更高版本上,Android.Permission API 要求在需要时,动态请求使用某些常用系统功能(例如相机、麦克风或位置)的权限,而不是在应用程序启动时立即请求权限。
Unity的Android版本,一样要遵守这个要求。
这里介绍2种方法,一种是C#直接请求,一种是C#调用Android的java代码请求。
Unity本身有动态权限的请求方法。但是这种比较局限,比如,无法获得权限请求的结果。anyway,这里还是介绍一下:
以/sdcard权限读取为例子:
using UnityEngine;
# if PLATFORM_ANDROID
using UnityEngine.Android;
# endif
public class PermissionTest : MonoBehaviour
{
GameObject dialog = null;
void Start ()
{
#if PLATFORM_ANDROID
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead))
{
Permission.RequestUserPermission(Permission.ExternalStorageRead);
dialog = new GameObject();
}
#endif
}
void OnGUI ()
{
#if PLATFORM_ANDROID
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead))
{
// 用户拒绝了使用的权限。
//显示一条包含 Yes/No 按钮的消息,说明需要该权限的原因。
//如果用户选择 yes,则再次提出请求
// 在此处显示对话框。
dialog.AddComponent<PermissionsRationaleDialog>();
return;
}
else if (dialog != null)
{
Destroy(dialog);
}
#endif
//现在可以用麦克风执行所需的操作了
}
}
Dialog的代码。
using UnityEngine;
# if PLATFORM_ANDROID
using UnityEngine.Android;
# endif
public class PermissionsRationaleDialog : MonoBehaviour
{
const int kDialogWidth = 300;
const int kDialogHeight = 100;
private bool windowOpen = true;
void DoMyWindow(int windowID)
{
GUI.Label(new Rect(10, 20, kDialogWidth - 20, kDialogHeight - 50), "Please let me use the storage.");
GUI.Button(new Rect(10, kDialogHeight - 30, 100, 20),"No");
if (GUI.Button(new Rect(kDialogWidth - 110, kDialogHeight - 30, 100, 20), "Yes"))
{
#if PLATFORM_ANDROID
Permission.RequestUserPermission(Permission.Microphone);
#endif
windowOpen = false;
}
}
void OnGUI ()
{
if (windowOpen)
{
Rect rect = new Rect((Screen.width / 2) - (kDialogWidth / 2), (Screen.height / 2) - (kDialogHeight / 2), kDialogWidth, kDialogHeight);
GUI.ModalWindow(0, rect, DoMyWindow, "Permissions Request Dialog");
}
}
}
应将 PermissionTest(而不是 PermissionsRationaleDialog)作为组件添加到游戏对象。PermissionTest会自动创建一个游戏对象,并在需要显示对话框时添加 PermissionsRationaleDialog。
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
//Android完成权限请求后的回调函数
public void onPermissionResult(String resultCode)
{
Debug.Log(TAG + "onPermissionResult resultCode " + resultCode);
if ("1".Equals(resultCode))
{
Invoke("preparePlay", 2);
}
else
{
Debug.Log(TAG + "not permission to read local file");
}
}
private void checkPermission()
{
Debug.Log(TAG + "checkPermission");
AndroidJavaObject nativeObject = new AndroidJavaObject("com.iqiyi.cutgreenvideosdk.PermissionHelper");
nativeObject.CallStatic("checkPermission", activity, "AndroidVideoScreen", "onPermissionResult");//AndroiwdVideoScreen 为脚本挂载的对象,onPermissionResult为脚本监听回调的函数名称
}
Android端需要拿到activity的实例,才可以发起请求,注意,application context是不可以的喔!
因为Android端没有activity的代码,所以也无法监听权限的回调。所以只能加一个handler轮询,得到权限后,通过消息告诉Untiy。
以下是具体代码:
package com.iqiyi.cutgreenvideosdk;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
import java.lang.ref.WeakReference;
public class PermissionHelper {
private static final String TAG = "PermissionHelper";
private MyHandler myHandler;
private Context mContext;
private static int checkCount = 0;
private static String mGameObject = "";
private static String mCallbackFunction = "";
private static class SingletonHolder {
private static final PermissionHelper INSTANCE = new PermissionHelper();
}
private PermissionHelper() {
myHandler = new MyHandler(this);
}
public static final PermissionHelper getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 请求权限
*
* @param context 必须为activity,否则framework会报错IllegalArgumentException: android.app.Application is not supported
* @param gameObject
* @param callbackFunction
*/
public static void checkPermission(Context context, String gameObject, String callbackFunction) {
Log.i(TAG, "checkPermission gameObject " + gameObject + " callbackFunction " + callbackFunction);
mGameObject = gameObject;
mCallbackFunction = callbackFunction;
if (context == null)
return;
getInstance().mContext = context;
boolean hasPermission = PermissionUtils.checkPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE);
if (hasPermission) {
Log.w(TAG, "checkPermission, has permission");
notifyResult(true);
} else {
showPermissionDialog(context);
}
}
private static void notifyResult(boolean permissionGranted) {
try {
//参数1, 脚本挂载的gameObject名称,参数2, 脚本方法,参数3,返回值
Log.w(TAG, "notifyResult, permissionGranted " + permissionGranted + " mGameObject " + mGameObject + " mCallbackFunction " + mCallbackFunction);
UnityPlayer.UnitySendMessage(mGameObject, mCallbackFunction, permissionGranted ? "1" : "0");
getInstance().mContext = null;
} catch (Exception e) {
e.printStackTrace();
}
}
private static void showPermissionDialog(final Context context) {
Log.w(TAG, "showPermissionDialog");
if (context == null)
return;
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("我们需要读存储权限来播放本地视频,您是否允许?");
builder.setCancelable(true);
builder.setPositiveButton(
"允许",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
reqPermission(context);
}
});
builder.setNegativeButton(
"取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
getInstance().myHandler.sendEmptyMessageDelayed(MyHandler.CHECK_PERMISSION, 2000);
}
private static void reqPermission(Context context) {
if (context instanceof Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
((Activity) context).requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PermissionUtils.REQ_CODE);
}
}
}
private static void checkPermission() {
checkCount++;
if (checkCount > 20) {
notifyResult(false);
return;
}
if (getInstance().mContext != null && PermissionUtils.checkPermission(getInstance().mContext, Manifest.permission.READ_EXTERNAL_STORAGE)) {
Log.w(TAG, "got permission");
notifyResult(true);
} else {
Log.w(TAG, "keep checkPermission");
getInstance().myHandler.sendEmptyMessageDelayed(MyHandler.CHECK_PERMISSION, 2000);
}
}
private static class MyHandler extends Handler {
private final WeakReference<PermissionHelper> mRefs;
public static final int CHECK_PERMISSION = 1;
public MyHandler(PermissionHelper instance) {
super(Looper.getMainLooper());
mRefs = new WeakReference<>(instance);
}
@Override
public void handleMessage(Message msg) {
if (mRefs.get() == null) {
return;
}
switch (msg.what) {
case CHECK_PERMISSION:
mRefs.get().checkPermission();
break;
default:
break;
}
}
}
}
有关Android的模块如何在Unity中使用,可以参考这篇文章:
https://blog.csdn.net/newchenxf/article/details/119934004