ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级

Android访问sd卡权限,各个版本有不同的方式。使用ARFoundation编程android项目时,可以使用unity提供的Permission申请android权限,提示有UnauthorizedAccessException的报错,基本为权限问题。

Android中sd卡的路径一般为:/storage/emulated/0/…

比如/storage/emulated/0/DCIM 为相机目录。

从《ARFoundation从零开始3-arfoundation项目》创建项目

一、android各版本的权限申请

1.安卓6.0(API 23)以下,访问只需要在清单文件中添加如下权限

2. 在安卓6.0(API 23)及以上系统,还需要在代码中动态申请权限

ActivityCompat.requestPermissions(MainActivity.this, permissions, PERMISSION_REQUEST);

3. 安卓10系统以上,还需要在清单文件中application节点加上:android:requestLegacyExternalStorage="true"

二、unity配置

1.新增自定义项AndroidManifest.xml,用来设置android权限的配置。Edit-ProjectSettings-Player-Publishing Settings,勾选自定义Manifest:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第1张图片

2.进入当前项目目录\Assets\Plugins\Android,修改AndroidManifest.xml文件:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第2张图片

修改主Activity为com.unity3d.player.MainActivity,文件内容修改为:

  android:requestLegacyExternalStorage="true">

    com.unity3d.player.MainActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false">

     

       

       

     

     

     

   

   

   

   

   

   

   

   

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 

2.进入当前项目\Assets\Plugins\Android目录,新建MainActivity.java文件,作为主启动Activity:ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第3张图片

3. 进入当前项目\Assets\Plugins\Android目录,mainTemplate.gradle.meta文件repositories修改为:

google()

       mavenCentral()

与android studio中保持一致!

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第4张图片

4.unity中-Project Settings-Player-Other Settings-Write Permission选择External:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第5张图片

5.MainActivity.java代码:

package com.unity3d.player;

import android.os.Bundle;

import android.view.KeyEvent;

import android.widget.Toast;

public class MainActivity extends UnityPlayerActivity{

    private static MainActivity instance;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        instance = this;

    }

    public static MainActivity GetInstance()

    {

        return instance;

    }

    @Override public boolean dispatchKeyEvent(KeyEvent event)

    {

        if(event.getKeyCode() == KeyEvent.KEYCODE_BACK){

            onBackPressed();

            return true;

        }

        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)

            return mUnityPlayer.injectEvent(event);

        return super.dispatchKeyEvent(event);

    }

    //------

    @Override

    public void onBackPressed() {

        runOnUiThread(new Runnable() {

            @Override

            public void run() {

                mUnityPlayer.quit();

            }

        });

        super.onBackPressed();

    }

    //unity调用android的方法

    public int Sum(int x, int y)

    {

        return x + y;

    }

    public String OnUnityFinished(String str){

        runOnUiThread(new Runnable() {

            @Override

            public void run() {

                Toast.makeText(

                        instance,

                        "OnUnityFinished=" + str,

                        Toast.LENGTH_LONG).show();

            }

        });

        return "ok";

    }

    public void CallUnityFun(String str)

    {

        String receiveObj = "MainCamera";//unity中脚本挂载的Object的name

        String receiveMethod = "Receive";//unity中Object挂载脚本的方法名

        String params = str + " Android Call Unity.";//方法要穿的参数

        //android调用unity,

        UnityPlayer.UnitySendMessage(receiveObj, receiveMethod, params);

    }

}

三、unity申请android权限代码

Unity中自带的Android权限申请类Permission:

Unity - Scripting API: Permission

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第6张图片

其中主要用到的方法:

HasUserAuthorizedPermission方法用来判断是否获得了该权限:

Permission.HasUserAuthorizedPermission("android.permission.READ_PHONE_STATE")

RequestUserPermission方法用来请求该权限:

Permission.RequestUserPermission("android.permission.READ_PHONE_STATE");

1.编写android权限申请类,项目Scripts文件夹下新建AndroidPermissions.cs文件,挂载到AR Session Origin下:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第7张图片

代码:

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.Android;

namespace FrameworkDesign.Example

{

    public class AndroidPermissions : MonoBehaviour

    {

        private static AndroidPermissions instance;

        private int index;

        private List<string> permissionList = new List<string>();

        private void Awake()

        {

            if(instance == null)

            {

                instance = this;

                Init();

            }                                 

        }

        //初始化,权限申请要尽可能早

        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]

        public void Init()

        {

            //权限添加进列表

            permissionList.Clear();

            index = 0;

            //permissionList.Add("android.permission.READ_PHONE_STATE");

            permissionList.Add(Permission.ExternalStorageRead);

            permissionList.Add(Permission.ExternalStorageWrite);

           // permissionList.Add(Permission.FineLocation);

           // permissionList.Add(Permission.CoarseLocation);

            StartCheckPermission(0.02f); //开始申请

            Logger.Log("权限申请完毕");

        }

        public void StartCheckPermission(float time)

        {

            //Logger.Log("开始权限申请");

            if (permissionList.Count > 0)

            {

                Get(permissionList[index], time);

            }

        }

        ///

        /// 判断并申请权限

        ///

        /// name="type">权限名

        /// name="time">如拒绝延迟多久再次申请

        void Get(string type, float time)

        {

            if (!Permission.HasUserAuthorizedPermission(type))

            {

                Permission.RequestUserPermission(type);

                Logger.Log("正在获取的权限:" + type);

                StartCoroutine(Check(type, time));

            }

            else

            {

                Logger.Log("权限已经获取:" + type);

                if (index < permissionList.Count - 1)

                {

                    index += 1;

                    Get(permissionList[index], time);

                }

            }

        }

        IEnumerator Check(string type, float time)

        {

            yield return new WaitForSeconds(time);

            Get(type, time);

        }

    }

}

2.打包运行:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第8张图片  

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第9张图片

当用户尚未授权时,程序弹出Android权限申请界面,点击授权即可。

四、unity导出lib库

unity导出lib库,(先删除原来导出的lib库文件夹下所有文件,确保修改的文件更新):

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第10张图片

五、android studio升级

1.java JDK升级到11,配置环境变量。

2.Android studio升级到2021.2.1:下载安装包安装,提示删除旧版,点击确定安装新版。

3. Android studio配置gradle,file-project structure-project,配置7.2.1和7.3.3:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第11张图片

点击SDK Location-Gradle Settings-Gradle JDK,选择11:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第12张图片

六、android studio导入unity库

1.复制unityLibrary到android studio工程根目录(先删除原有unityLibrary文件夹),启动android studio

2.gradle.properties文件注释掉android.enableR8=false
#android.enableR8=false

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第13张图片

3.app的build.gradle的buildToolsVersion 
buildToolsVersion '30.0.3'

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第14张图片

4.打包出错:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第15张图片

原因是androidx兼容问题,android代码使用了androidx,删除unityLibrary的build.gradle内以下内容:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第16张图片

打包成功

MainActivity 继承UnityPlayerActivity,实现与unity的接口调用,相关代码都在MainActivity中编写。

三、android打包运行

如未配置,参看《ARFoundation从零开始3-arfoundation项目》。

安装运行:

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第17张图片  

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第18张图片

ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级_第19张图片

对于Unity工程不单独打包,而是接入到其他android工程里的情况,android权限的申请最好在android端进行,不能确保在android申请的时候再在unity端申请。

Android端申请权限代码:



//----1.android端申请权限,以下代码放到当前Activity类里-----------------

//------2.在当前ActivityonCreate方法里调用checkPermission();

String[] permissions = new String[]{Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_SETTINGS};

List mPermissionList = new ArrayList<>();



private static final int PERMISSION_REQUEST = 1;

// 检查权限

private void checkPermission() {

    mPermissionList.clear();

    //判断哪些权限未授予

    for (int i = 0; i < permissions.length; i++) {

        if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {

            mPermissionList.add(permissions[i]);

        }

    }

    //判断是否为空

    if (mPermissionList.isEmpty()) {//未授予的权限为空,表示都授予了



    } else {//请求权限方法

        String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);//List转为数组

        ActivityCompat.requestPermissions(MainActivity.this, permissions, PERMISSION_REQUEST);

    }

}

/**

 * 响应授权

 * 这里不管用户是否拒绝,都进入首页,不再重复申请权限

 */

@Override

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode) {

        case PERMISSION_REQUEST:



            break;

        default:

            super.onRequestPermissionsResult(requestCode, permissions, grantResults);

            break;

    }

}

//----android端申请权限-----------------

四、常见问题

(unity的gradle没有与android studio同步,仍使用的gradle6.7.1+jdk1.8,没有升级到gradle7.3.3+jdk11)

五、参考资料

1. Unity api:

Unity - Scripting API: Permission

2.ARFoundation示例:

GitHub - Unity-Technologies/arfoundation-samples: Example content for Unity projects based on AR Foundation

3.ARCore文档:

在 Unity (AR Foundation) 应用中执行光线投射  |  ARCore  |  Google Developers

你可能感兴趣的:(ARFoundation,android,unity,游戏引擎,android,studio,ar)