您需要Java代码来请求权限,并且需要从Unity的C#运行时接口进入该Java代码。 您需要创建一个Unity插件来实现此功能。
下面是我创建的插件,用于在运行时授予WRITE_EXTERNAL_STORAGE权限。
您需要像这样的项目结构:
Plugins/
Android/
NoodlePermissionGranter/
project.properties
AndroidManifest.xml
NoodlePermissionGranter.cs
libs/
NoodlePermissionGranter.jar
NoodlePermissionGranter.cs:
using UnityEngine;
using System.Collections;
using System;
public class NoodlePermissionGranter : MonoBehaviour {
public static Action<bool> PermissionRequestCallback;
public enum NoodleAndroidPermission
{
WRITE_EXTERNAL_STORAGE
}
public static void GrantPermission(NoodleAndroidPermission permission)
{
if (!initialized)
initialize ();
noodlePermissionGranterClass.CallStatic ("grantPermission", activity, (int)permission);
}
private static NoodlePermissionGranter instance;
private static bool initialized = false;
public void Awake()
{
instance = this;
DontDestroyOnLoad (this.gameObject);
if (name != NOODLE_PERMISSION_GRANTER)
name = NOODLE_PERMISSION_GRANTER;
}
private static void initialize()
{
if (instance == null) {
GameObject go = new GameObject();
instance = go.AddComponent<NoodlePermissionGranter>();
go.name = NOODLE_PERMISSION_GRANTER;
}
noodlePermissionGranterClass = new AndroidJavaClass("com.noodlecake.unityplugins.NoodlePermissionGranter");
AndroidJavaClass u3d = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
activity = u3d.GetStatic<AndroidJavaObject> ("currentActivity");
initialized = true;
}
static AndroidJavaClass noodlePermissionGranterClass;
static AndroidJavaObject activity;
private const string WRITE_EXTERNAL_STORAGE="WRITE_EXTERNAL_STORAGE";
private const string PERMISSION_GRANTED = "PERMISSION_GRANTED";
private const string PERMISSION_DENIED = "PERMISSION_DENIED";
private const string NOODLE_PERMISSION_GRANTER = "NoodlePermissionGranter";
private void permissionRequestCallbackInternal(string message)
{
bool permissionGranted = (message == PERMISSION_GRANTED);
if (PermissionRequestCallback != null)
PermissionRequestCallback (permissionGranted);
}
}
NoodlePermissionGranter.java:
package com.noodlecake.unityplugins;
import android.Manifest;
import android.os.Build;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.util.Log;
import android.content.pm.PackageManager;
import java.io.File;
import com.unity3d.player.UnityPlayerActivity;
import com.unity3d.player.UnityPlayer;
public class NoodlePermissionGranter
{
private final static String UNITY_CALLBACK_GAMEOBJECT_NAME = "NoodlePermissionGranter";
private final static String UNITY_CALLBACK_METHOD_NAME = "permissionRequestCallbackInternal";
private final static String PERMISSION_GRANTED = "PERMISSION_GRANTED";
private final static String PERMISSION_DENIED = "PERMISSION_DENIED";
public static String getPermissionStringFromEnumInt(int permissionEnum) throws Exception
{
switch (permissionEnum)
{
case 0:
return Manifest.permission.WRITE_EXTERNAL_STORAGE;
}
Log.e("NoodlePermissionGranter", "Error. Unknown permissionEnum " + permissionEnum);
throw new Exception(String.format("Error. Unknown permissionEnum %d",permissionEnum));
}
public static void grantPermission(Activity currentActivity, int permissionEnum)
{
final Activity act = currentActivity;
Log.i("NoodlePermissionGranter","grantPermission " + permissionEnum) ;
if (Build.VERSION.SDK_INT < 23) {
Log.i("NoodlePermissionGranter","Build.VERSION.SDK_INT < 23 (" + Build.VERSION.SDK_INT+")");
UnityPlayer.UnitySendMessage(UNITY_CALLBACK_GAMEOBJECT_NAME, UNITY_CALLBACK_METHOD_NAME, PERMISSION_GRANTED);
return;
}
try
{
final int PERMISSIONS_REQUEST_CODE = permissionEnum;
final String permissionFromEnumInt = getPermissionStringFromEnumInt(permissionEnum);
if (currentActivity.checkCallingOrSelfPermission(permissionFromEnumInt) == PackageManager.PERMISSION_GRANTED) {
Log.i("NoodlePermissionGranter", "already granted");
UnityPlayer.UnitySendMessage(UNITY_CALLBACK_GAMEOBJECT_NAME, UNITY_CALLBACK_METHOD_NAME, PERMISSION_GRANTED);
return;
}
final FragmentManager fragmentManager = currentActivity.getFragmentManager();
final Fragment request = new Fragment() {
@Override public void onStart()
{
super.onStart();
Log.i("NoodlePermissionGranter","fragment start");
String[] permissionsToRequest = new String [] {permissionFromEnumInt};
Log.i("NoodlePermissionGranter","fragment start " + permissionsToRequest[0]);
requestPermissions(permissionsToRequest, PERMISSIONS_REQUEST_CODE);
}
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
Log.i("NoodlePermissionGranter", "onRequestPermissionsResult");
if (requestCode != PERMISSIONS_REQUEST_CODE)
return;
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("NoodlePermissionGranter", PERMISSION_GRANTED);
UnityPlayer.UnitySendMessage(UNITY_CALLBACK_GAMEOBJECT_NAME, UNITY_CALLBACK_METHOD_NAME, PERMISSION_GRANTED);
} else {
Log.i("NoodlePermissionGranter",PERMISSION_DENIED);
UnityPlayer.UnitySendMessage(UNITY_CALLBACK_GAMEOBJECT_NAME, UNITY_CALLBACK_METHOD_NAME, PERMISSION_DENIED);
}
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(this);
fragmentTransaction.commit();
}
};
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(0, request);
fragmentTransaction.commit();
}
catch(Exception error)
{
Log.w("[NoodlePermissionGranter]", String.format("Unable to request permission: %s", error.getMessage()));
UnityPlayer.UnitySendMessage(UNITY_CALLBACK_GAMEOBJECT_NAME, UNITY_CALLBACK_METHOD_NAME, PERMISSION_DENIED);
}
}
}
BuildNoodlePermissionGranter.sh
export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
ClASSPATH=$UNITY_ROOT"/Unity.app/Contents/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes/classes.jar"
javac NoodlePermissionGranter.java -bootclasspath $ANDROID_SDK_ROOT/platforms/android-23/android.jar -classpath $ClASSPATH -d .
javap -s com.noodlecake.unityplugins.NoodlePermissionGranter
jar cvfM NoodlePermissionGranter.jar com/
rm -rf com
为了让Unity打包一个位于Plugins/Android/libs之外的jar文件,您需要project.properties和一个虚拟的AndroidManifest.xml
project.properties
target=android-9
android.library=true
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.noodlecake.unityplugins.noodlepermissiongranter"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:targetSdkVersion="23" />
</manifest>
如果PermissionRequestCallback可以提供所请求的权限枚举作为参数,那将是很好的,但UnityPlayer.UnitySendMessage仅支持单个字符串参数,并且我决定不实现字符串序列化(使用JSON来做这件事是一个不错的选择)。