首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在unity3d中实现Android6.0权限

在unity3d中实现Android6.0权限
EN

Stack Overflow用户
提问于 2016-01-27 09:06:18
回答 5查看 22.8K关注 0票数 6

我已经安装了Android Support Library,但在developer.android网站上显示,为了在我的项目中实现它,我需要编辑我没有的build.gradle文件,因为它是Unity项目。

我已经创建了一个复制该网站内容的build.gradle文件:http://gradleplease.appspot.com/,并将该文件放在我的Unity项目的根目录下,但是当我尝试使用该库时,它不起作用

if (ContextCompat.checkSelfPermission(thisActivity,
                                      Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
                                                            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                                          new String[]{Manifest.permission.READ_CONTACTS},
        MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}
EN

回答 5

Stack Overflow用户

发布于 2016-02-13 02:34:57

你需要Java代码来请求许可,并且你需要一个从Unity的C#运行时到上述Java代码的接口。为此,您需要创建一个Unity Plugin

下面是我创建的在运行时授予WRITE_EXTERNAL_STORAGE权限的插件。

你需要一个像这样的项目结构:

Plugins/
  Android/
    NoodlePermissionGranter/
      project.properties
      AndroidManifest.xml
      NoodlePermissionGranter.cs
      libs/
        NoodlePermissionGranter.jar

NoodlePermissionGranter.cs:

      ///////////////////////////////////////////////////////////
     ///////////////// NoodlePermissionGranter /////////////////
    /// Implements runtime granting of Android permissions. ///
   /// This is necessary for Android M (6.0) and above. //////
  ///////////////////////////////////////////////////////////   
 //////////////////// Noodlecake Studios ///////////////////
///////////////////////////////////////////////////////////

using UnityEngine;
using System.Collections;
using System;

public class NoodlePermissionGranter : MonoBehaviour {

    // subscribe to this callback to see if your permission was granted.
    public static Action<bool> PermissionRequestCallback;

    // for now, it only implements the external storage permission
    public enum NoodleAndroidPermission
    {
        WRITE_EXTERNAL_STORAGE
    }
    public static void GrantPermission(NoodleAndroidPermission permission) 
    {
        if (!initialized)
            initialize ();

        noodlePermissionGranterClass.CallStatic ("grantPermission", activity, (int)permission);
    }







      //////////////////////////////
     /// Initialization Stuff /////
    //////////////////////////////

    // it's a singleton, but no one needs to know about it. hush hush. dont touch me.
    private static NoodlePermissionGranter instance;
    private static bool initialized = false;

    public void Awake()
    {
        // instance is also set in initialize.
        // having it here ensures this thing doesnt break
        // if you added this component to the scene manually
        instance = this;
        DontDestroyOnLoad (this.gameObject);
        // object name must match UnitySendMessage call in NoodlePermissionGranter.java
        if (name != NOODLE_PERMISSION_GRANTER)
            name = NOODLE_PERMISSION_GRANTER;
    }


    private static void initialize()
    {
        // runs once when you call GrantPermission

        // add object to scene
        if (instance == null) {
            GameObject go = new GameObject();
            // instance will also be set in awake, but having it here as well seems extra safe
            instance = go.AddComponent<NoodlePermissionGranter>();
            // object name must match UnitySendMessage call in NoodlePermissionGranter.java
            go.name = NOODLE_PERMISSION_GRANTER; 
        }

        // get the jni stuff. we need the activty class and the NoodlePermissionGranter class.
        noodlePermissionGranterClass = new AndroidJavaClass("com.noodlecake.unityplugins.NoodlePermissionGranter");
        AndroidJavaClass u3d = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        activity = u3d.GetStatic<AndroidJavaObject> ("currentActivity");

        initialized = true;
    }







      ///////////////////
     //// JNI Stuff ////
    ///////////////////

    static AndroidJavaClass noodlePermissionGranterClass;
    static AndroidJavaObject activity;
    private const string WRITE_EXTERNAL_STORAGE="WRITE_EXTERNAL_STORAGE";
    private const string PERMISSION_GRANTED = "PERMISSION_GRANTED"; // must match NoodlePermissionGranter.java
    private const string PERMISSION_DENIED = "PERMISSION_DENIED"; // must match NoodlePermissionGranter.java
    private const string NOODLE_PERMISSION_GRANTER = "NoodlePermissionGranter"; // must match UnitySendMessage call in NoodlePermissionGranter.java

    private void permissionRequestCallbackInternal(string message)
    {
        // were calling this method from the java side.
        // the method name and gameobject must match NoodlePermissionGranter.java's UnitySendMessage
        bool permissionGranted = (message == PERMISSION_GRANTED);
        if (PermissionRequestCallback != null)
            PermissionRequestCallback (permissionGranted);
    }
}

NoodlePermissionGranter.java:

package com.noodlecake.unityplugins;


      ///////////////////////////////////////////////////////////
     ///////////////// NoodlePermissionGranter /////////////////
    /// Implements runtime granting of Android permissions. ///
   /// This is necessary for Android M (6.0) and above. //////
  ///////////////////////////////////////////////////////////   
 //////////////////// Noodlecake Studios ///////////////////
///////////////////////////////////////////////////////////

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
{
    // Only implements WRITE_EXTERNAL_STORAGE so far.
    // Implement the rest by matching the enum in NoodlePermissionGranter.cs
    // to the getPermissionStringFromEnumInt below.

    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"; // this will be an arg to the above method
    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;
            // "and the rest is still unwritten" - Natasha Bedingfield
        }
        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)
    {
        // permission enum must match ordering in NoodlePermissionGranter.cs
        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) {
                        // permission was granted, yay! Do the
                        // contacts-related task you need to do.
                        Log.i("NoodlePermissionGranter", PERMISSION_GRANTED);
                        UnityPlayer.UnitySendMessage(UNITY_CALLBACK_GAMEOBJECT_NAME, UNITY_CALLBACK_METHOD_NAME, PERMISSION_GRANTED);
                    } else {

                        // permission denied, boo! Disable the
                        // functionality that depends on this permission.
                        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();

                    // shouldBeOkayToStartTheApplicationNow();
                }
            };

            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来实现序列化将是一个很好的选择)。

票数 27
EN

Stack Overflow用户

发布于 2016-08-19 04:34:24

除了Jason为Unity 5.3.3及更高版本编写的优秀代码(我使用的是5.4)之外,我还在清单中添加了以下代码,以阻止Unity在启动时自动询问:

 <application>
     <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
 </application>
票数 6
EN

Stack Overflow用户

发布于 2016-04-08 20:37:57

除了Jason Knight的帖子(我用它作为我自己的Unity插件来处理运行时权限):

我使用Android studio创建了一个插件。我遵循了以下站点上的说明,并完美地工作:http://www.thegamecontriver.com/2015/04/android-plugin-unity-android-studio.html

我还使用shouldShowRequestPermissionRationale()函数添加了另一个方法,以便在用户拒绝权限并选中“不再询问”复选框的情况下隐藏某些UI元素。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35027043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档