using UnityEngine; using System; /// /// Android平台数据导出权限管理器 /// 处理Android平台导出数据所需的存储权限 /// public static class AndroidExportPermissionManager { /// /// 检查是否有外部存储写入权限 /// public static bool HasWriteExternalStoragePermission() { #if UNITY_ANDROID && !UNITY_EDITOR try { using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityClass.GetStatic("currentActivity")) using (var context = currentActivity.Call("getApplicationContext")) { var permissionClass = new AndroidJavaClass("android.Manifest$permission"); string writePermission = permissionClass.GetStatic("WRITE_EXTERNAL_STORAGE"); var contextCompat = new AndroidJavaClass("androidx.core.content.ContextCompat"); int result = contextCompat.CallStatic("checkSelfPermission", context, writePermission); return result == 0; // PackageManager.PERMISSION_GRANTED = 0 } } catch (Exception ex) { Debug.LogError($"检查存储权限失败: {ex.Message}"); return false; } #else return true; // 非Android平台默认有权限 #endif } /// /// 请求外部存储写入权限 /// public static void RequestWriteExternalStoragePermission() { #if UNITY_ANDROID && !UNITY_EDITOR try { using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityClass.GetStatic("currentActivity")) { var permissionClass = new AndroidJavaClass("android.Manifest$permission"); string writePermission = permissionClass.GetStatic("WRITE_EXTERNAL_STORAGE"); // 检查是否需要显示权限说明 var activityCompat = new AndroidJavaClass("androidx.core.app.ActivityCompat"); bool shouldShow = activityCompat.CallStatic("shouldShowRequestPermissionRationale", currentActivity, writePermission); if (shouldShow) { ShowPermissionRationale(); } // 请求权限 string[] permissions = { writePermission }; activityCompat.CallStatic("requestPermissions", currentActivity, permissions, 1001); Debug.Log("已请求存储权限"); } } catch (Exception ex) { Debug.LogError($"请求存储权限失败: {ex.Message}"); } #endif } /// /// 检查是否有管理外部存储权限(Android 11+) /// public static bool HasManageExternalStoragePermission() { #if UNITY_ANDROID && !UNITY_EDITOR try { // Android 11 (API 30) 及以上需要MANAGE_EXTERNAL_STORAGE权限 var buildVersion = new AndroidJavaClass("android.os.Build$VERSION"); int sdkInt = buildVersion.GetStatic("SDK_INT"); if (sdkInt >= 30) // Android 11+ { var environment = new AndroidJavaClass("android.os.Environment"); return environment.CallStatic("isExternalStorageManager"); } else { // Android 10及以下使用传统权限 return HasWriteExternalStoragePermission(); } } catch (Exception ex) { Debug.LogError($"检查管理外部存储权限失败: {ex.Message}"); return false; } #else return true; #endif } /// /// 请求管理外部存储权限(Android 11+) /// public static void RequestManageExternalStoragePermission() { #if UNITY_ANDROID && !UNITY_EDITOR try { var buildVersion = new AndroidJavaClass("android.os.Build$VERSION"); int sdkInt = buildVersion.GetStatic("SDK_INT"); if (sdkInt >= 30) // Android 11+ { using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityClass.GetStatic("currentActivity")) { var intent = new AndroidJavaObject("android.content.Intent"); intent.Call("setAction", "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION"); var uri = new AndroidJavaClass("android.net.Uri"); var packageUri = uri.CallStatic("parse", "package:" + currentActivity.Call("getPackageName")); intent.Call("setData", packageUri); currentActivity.Call("startActivity", intent); Debug.Log("已打开管理外部存储权限设置页面"); } } else { // Android 10及以下使用传统权限请求 RequestWriteExternalStoragePermission(); } } catch (Exception ex) { Debug.LogError($"请求管理外部存储权限失败: {ex.Message}"); } #endif } /// /// 获取推荐的导出目录 /// public static string GetRecommendedExportDirectory() { #if UNITY_ANDROID && !UNITY_EDITOR try { using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityClass.GetStatic("currentActivity")) { var buildVersion = new AndroidJavaClass("android.os.Build$VERSION"); int sdkInt = buildVersion.GetStatic("SDK_INT"); if (sdkInt >= 29) // Android 10+,使用分区存储 { // 使用应用专用目录,无需权限 var context = currentActivity.Call("getApplicationContext"); var externalFilesDir = context.Call("getExternalFilesDir", "Documents"); if (externalFilesDir != null) { return externalFilesDir.Call("getAbsolutePath"); } else { return Application.persistentDataPath; } } else { // Android 9及以下,使用公共目录 var environment = new AndroidJavaClass("android.os.Environment"); var externalStorage = environment.CallStatic("getExternalStorageDirectory"); string storagePath = externalStorage.Call("getAbsolutePath"); return System.IO.Path.Combine(storagePath, "Download", "DCX_Export"); } } } catch (Exception ex) { Debug.LogError($"获取导出目录失败: {ex.Message}"); return Application.persistentDataPath; } #else return System.IO.Path.Combine(System.Environment.GetFolderPath( System.Environment.SpecialFolder.Desktop), "DCX_Export"); #endif } /// /// 获取应用内部稳定目录。Android 7+优先使用Device Protected Storage, /// 可在系统刚启动且用户未解锁时访问,适合作为历史索引主存储。 /// public static string GetStableAppInternalDirectory() { #if UNITY_ANDROID && !UNITY_EDITOR try { using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityClass.GetStatic("currentActivity")) { var context = currentActivity.Call("getApplicationContext"); try { using (var buildVersion = new AndroidJavaClass("android.os.Build$VERSION")) { int sdkInt = buildVersion.GetStatic("SDK_INT"); if (sdkInt >= 24) { var deviceProtectedContext = context.Call("createDeviceProtectedStorageContext"); if (deviceProtectedContext != null) { var deviceProtectedDir = deviceProtectedContext.Call("getFilesDir"); if (deviceProtectedDir != null) { return deviceProtectedDir.Call("getAbsolutePath"); } } } } } catch (Exception ex) { Debug.LogWarning($"获取Device Protected Storage失败,回退内部目录: {ex.Message}"); } var filesDir = context.Call("getFilesDir"); if (filesDir != null) { return filesDir.Call("getAbsolutePath"); } } } catch (Exception ex) { Debug.LogWarning($"获取应用内部稳定目录失败: {ex.Message}"); } return Application.persistentDataPath; #else return Application.persistentDataPath; #endif } /// /// 检查导出目录是否可访问 /// public static bool IsExportDirectoryAccessible(string directory) { try { if (!System.IO.Directory.Exists(directory)) { System.IO.Directory.CreateDirectory(directory); } // 尝试写入测试文件 string testFile = System.IO.Path.Combine(directory, "test.txt"); System.IO.File.WriteAllText(testFile, "test"); if (System.IO.File.Exists(testFile)) { System.IO.File.Delete(testFile); return true; } return false; } catch (Exception ex) { Debug.LogWarning($"目录访问测试失败: {ex.Message}"); return false; } } /// /// 显示权限说明 /// private static void ShowPermissionRationale() { string message = "数据导出功能需要存储权限来保存文件到设备存储空间。\n\n" + "请在弹出的权限请求中选择'允许',以便:\n" + "• 导出BFI测试报告\n" + "• 保存折线图图片\n" + "• 导出历史数据"; Debug.Log($"权限说明: {message}"); // 在实际应用中,这里应该显示一个用户友好的对话框 } /// /// 获取存储权限状态说明 /// public static string GetPermissionStatusDescription() { #if UNITY_ANDROID && !UNITY_EDITOR var buildVersion = new AndroidJavaClass("android.os.Build$VERSION"); int sdkInt = buildVersion.GetStatic("SDK_INT"); if (sdkInt >= 30) // Android 11+ { bool hasPermission = HasManageExternalStoragePermission(); if (hasPermission) { return "✓ 已获得管理外部存储权限,可以导出数据到任何位置"; } else { return "⚠ 需要管理外部存储权限才能导出数据到公共目录"; } } else if (sdkInt >= 23) // Android 6.0+ { bool hasPermission = HasWriteExternalStoragePermission(); if (hasPermission) { return "✓ 已获得存储权限,可以导出数据"; } else { return "⚠ 需要存储权限才能导出数据"; } } else { return "✓ 系统版本较低,无需额外权限"; } #else return "✓ 当前平台无权限限制"; #endif } /// /// 处理权限请求结果 /// public static void HandlePermissionResult(string permission, bool granted) { if (permission.Contains("WRITE_EXTERNAL_STORAGE")) { if (granted) { Debug.Log("存储权限已获得,可以开始导出数据"); } else { Debug.LogWarning("存储权限被拒绝,数据导出功能将受限"); ShowPermissionDeniedGuidance(); } } } /// /// 显示权限被拒绝时的指导 /// private static void ShowPermissionDeniedGuidance() { string message = "存储权限被拒绝,您仍然可以:\n\n" + "1. 使用应用内部存储(容量有限)\n" + "2. 通过分享功能发送数据\n" + "3. 前往设置手动开启存储权限\n\n" + "建议开启权限以获得完整的导出功能。"; Debug.Log($"权限拒绝指导: {message}"); } }