| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> ARFoundation入门教程U1-android权限申请和导出unityLibrary库配置升级 -> 正文阅读 |
|
[游戏开发]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)以下,访问只需要在清单文件中添加如下权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
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: 2.进入当前项目目录\Assets\Plugins\Android,修改AndroidManifest.xml文件: 修改主Activity为com.unity3d.player.MainActivity,文件内容修改为: <?xml version="1.0" encoding="utf-8"?> <!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools"> ? <application android:requestLegacyExternalStorage="true"> ??? <activity android:name="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"> ????? <intent-filter> ??????? <action android:name="android.intent.action.MAIN" /> ??????? <category android:name="android.intent.category.LAUNCHER" /> ????? </intent-filter> ????? <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> ????? <meta-data android:name="android.notch_support" android:value="true" /> ??? </activity> ??? <meta-data android:name="unity.splash-mode" android:value="0" /> ??? <meta-data android:name="unity.splash-enable" android:value="True" /> ??? <meta-data android:name="notch.config" android:value="portrait|landscape" /> ??? <meta-data android:name="unity.build-id" android:value="…" /> ??? <meta-data android:name="com.google.android.ar.API_KEY" android:value="…" /> ??? <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" /> ??? <meta-data android:name="com.google.ar.core" android:value="required" /> ? </application> ? <uses-feature android:glEsVersion="0x00030000" /> ? <uses-permission android:name="android.permission.INTERNET" /> ? <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ? <uses-feature android:name="android.hardware.location.gps" android:required="True" /> ? <uses-feature android:name="android.hardware.location" android:required="True" /> ? <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ??? <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ? <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> ? <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" /> ? <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" /> ? <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:minSdkVersion="31" /> ? <uses-permission android:name="android.permission.CAMERA" /> ? <uses-feature android:name="android.hardware.camera.ar" android:required="true" /> ? <uses-feature android:name="com.google.ar.core.depth" android:required="true" /> </manifest> 2.进入当前项目\Assets\Plugins\Android目录,新建MainActivity.java文件,作为主启动Activity: 3. 进入当前项目\Assets\Plugins\Android目录,mainTemplate.gradle.meta文件repositories修改为: google() ?????? mavenCentral() 与android studio中保持一致! 4.unity中-Project Settings-Player-Other Settings-Write Permission选择External: 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 其中主要用到的方法: HasUserAuthorizedPermission方法用来判断是否获得了该权限: Permission.HasUserAuthorizedPermission("android.permission.READ_PHONE_STATE") RequestUserPermission方法用来请求该权限: Permission.RequestUserPermission("android.permission.READ_PHONE_STATE"); 1.编写android权限申请类,项目Scripts文件夹下新建AndroidPermissions.cs文件,挂载到AR Session Origin下: 代码: 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); ??????????? } ??????? } ??????? /// <summary> ??????? /// 判断并申请权限 ??????? /// </summary> ??????? /// <param name="type">权限名</param> ??????? /// <param name="time">如拒绝延迟多久再次申请</param> ??????? 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.打包运行: ?? 当用户尚未授权时,程序弹出Android权限申请界面,点击授权即可。 四、unity导出lib库unity导出lib库,(先删除原来导出的lib库文件夹下所有文件,确保修改的文件更新): 五、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: 点击SDK Location-Gradle Settings-Gradle JDK,选择11: 六、android studio导入unity库1.复制unityLibrary到android studio工程根目录(先删除原有unityLibrary文件夹),启动android studio 2.gradle.properties文件注释掉android.enableR8=false:
#android.enableR8=false
3.app的build.gradle的buildToolsVersion :
buildToolsVersion '30.0.3'
4.打包出错: 原因是androidx兼容问题,android代码使用了androidx,删除unityLibrary的build.gradle内以下内容: 打包成功 MainActivity 继承UnityPlayerActivity,实现与unity的接口调用,相关代码都在MainActivity中编写。 三、android打包运行如未配置,参看《ARFoundation从零开始3-arfoundation项目》。 安装运行: ?? 对于Unity工程不单独打包,而是接入到其他android工程里的情况,android权限的申请最好在android端进行,不能确保在android申请的时候再在unity端申请。 Android端申请权限代码:
//----1.android端申请权限,以下代码放到当前Activity类里-----------------
//------2.在当前Activity的onCreate方法里调用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<String> 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示例: 3.ARCore文档: 在 Unity (AR Foundation) 应用中执行光线投射 ?|? ARCore ?|? Google Developers |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 6:05:45- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |