Unity中通过AndroidJavaClass申请Android11+外部存储权限求助
Unity Android 11+ 申请全文件访问权限解决方案
你的代码存在两个核心问题:
ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION是Android 11(API 30)新增的静态常量字段,不是方法,不能用Call<String>调用,必须用GetStatic<String>获取。- 直接用
Context的Java类调用startActivity是错误的,必须使用当前活跃的Unity PlayerActivity实例来启动Intent。
以下是完整的解决步骤:
第一步:配置AndroidManifest.xml
在Unity项目的Plugins/Android目录下的AndroidManifest.xml中添加以下配置:
<!-- 申请Android 11+全文件访问权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <!-- 兼容Android 10及以下版本的存储访问逻辑 --> <application android:requestLegacyExternalStorage="true"> <!-- 保留原有application标签内的其他配置 --> </application>
第二步:编写C#权限处理代码
替换你原来的代码,使用以下完整实现:
using UnityEngine; using UnityEngine.Android; using System.Collections; public class StoragePermissionHandler : MonoBehaviour { public UnityEngine.UI.Text myConsole; // 调用此方法触发权限申请 public void RequestStoragePermission() { if (Application.platform != RuntimePlatform.Android) return; int androidSDKVersion = GetAndroidSDKVersion(); // Android 10及以下版本,用Unity原生权限申请 if (androidSDKVersion < 30) { if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite)) { Permission.RequestUserPermission(Permission.ExternalStorageWrite); } else { myConsole.text += "已拥有存储权限\n"; } return; } // Android 11+,先检查是否已有权限 if (HasManageExternalStoragePermission()) { myConsole.text += "已拥有全文件访问权限\n"; return; } // 跳转至系统权限设置页 try { AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); AndroidJavaClass settingsClass = new AndroidJavaClass("android.provider.Settings"); string action = settingsClass.GetStatic<string>("ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION"); AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", action); intent.Call<AndroidJavaObject>("setData", AndroidJavaObject.Parse("package:" + Application.identifier)); currentActivity.Call("startActivity", intent); StartCoroutine(CheckPermissionAfterUserAction(2f)); } catch (System.Exception e) { myConsole.text += "权限申请出错:" + e.ToString() + "\n"; } } // 检查是否已获取全文件访问权限 private bool HasManageExternalStoragePermission() { AndroidJavaClass environmentClass = new AndroidJavaClass("android.os.Environment"); AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); return environmentClass.CallStatic<bool>("isExternalStorageManager"); } // 获取当前Android系统SDK版本 private int GetAndroidSDKVersion() { AndroidJavaClass buildVersionClass = new AndroidJavaClass("android.os.Build$VERSION"); return buildVersionClass.GetStatic<int>("SDK_INT"); } // 用户操作权限设置后,延迟检查权限状态 private IEnumerator CheckPermissionAfterUserAction(float delay) { yield return new WaitForSeconds(delay); if (HasManageExternalStoragePermission()) { myConsole.text += "用户已授予全文件访问权限\n"; } else { myConsole.text += "用户拒绝了全文件访问权限\n"; } } }
代码说明
- 版本区分:自动适配Android 10及以下、Android 11+的不同权限逻辑
- 正确的上下文获取:使用
UnityPlayer.currentActivity作为启动Intent的上下文,避免空指针或无效调用 - 权限状态检查:通过Android原生API
isExternalStorageManager()判断权限是否已授予 - 操作后状态确认:跳转至设置页后延迟检查权限,确保能捕获用户的操作结果
内容的提问来源于stack exchange,提问作者Kamal Azizov
相关产品推荐
相关产品推荐

