DCS/ruiyiweiUX/Assets/Scripts/Managers/AndroidExportPermissionMana...

383 lines
14 KiB
C#
Raw Normal View History

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