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

383 lines
14 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}");
}
}