303 lines
11 KiB
C#
303 lines
11 KiB
C#
|
|
using System;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 跨平台时间设置权限管理器
|
|||
|
|
/// 处理不同平台设置系统时间所需的权限和限制
|
|||
|
|
/// </summary>
|
|||
|
|
public static class TimeSettingsPermissionManager
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查是否有设置系统时间的权限
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>是否有权限</returns>
|
|||
|
|
public static bool HasTimeSettingsPermission()
|
|||
|
|
{
|
|||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|||
|
|
return CheckWindowsTimePermission();
|
|||
|
|
#elif UNITY_ANDROID && !UNITY_EDITOR
|
|||
|
|
return CheckAndroidTimePermission();
|
|||
|
|
#else
|
|||
|
|
return true; // 编辑器模式总是返回true
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 请求时间设置权限或引导用户
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>是否成功获得权限或完成引导</returns>
|
|||
|
|
public static bool RequestTimeSettingsPermission()
|
|||
|
|
{
|
|||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|||
|
|
return RequestWindowsTimePermission();
|
|||
|
|
#elif UNITY_ANDROID && !UNITY_EDITOR
|
|||
|
|
return RequestAndroidTimePermission();
|
|||
|
|
#else
|
|||
|
|
Debug.Log("[模拟] 时间设置权限请求");
|
|||
|
|
return true;
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取当前平台时间设置的限制信息
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>权限限制描述</returns>
|
|||
|
|
public static string GetTimeSettingsLimitations()
|
|||
|
|
{
|
|||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|||
|
|
return "Windows平台需要管理员权限才能修改系统时间。应用会提示用户授权。";
|
|||
|
|
#elif UNITY_ANDROID && !UNITY_EDITOR
|
|||
|
|
return "Android平台普通应用无法直接修改系统时间。应用会引导用户到系统设置页面手动修改。";
|
|||
|
|
#else
|
|||
|
|
return "开发模式:无权限限制";
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查Windows平台时间设置权限
|
|||
|
|
/// </summary>
|
|||
|
|
private static bool CheckWindowsTimePermission()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 检查是否以管理员身份运行
|
|||
|
|
using (var identity = System.Security.Principal.WindowsIdentity.GetCurrent())
|
|||
|
|
{
|
|||
|
|
var principal = new System.Security.Principal.WindowsPrincipal(identity);
|
|||
|
|
bool isAdmin = principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
|
|||
|
|
|
|||
|
|
if (isAdmin)
|
|||
|
|
{
|
|||
|
|
Debug.Log("Windows: 应用以管理员身份运行,可以设置系统时间");
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("Windows: 应用未以管理员身份运行,设置系统时间可能失败");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"Windows权限检查失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 请求Windows时间设置权限
|
|||
|
|
/// </summary>
|
|||
|
|
private static bool RequestWindowsTimePermission()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (CheckWindowsTimePermission())
|
|||
|
|
{
|
|||
|
|
return true; // 已有权限
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.LogWarning("Windows: 需要管理员权限设置系统时间");
|
|||
|
|
|
|||
|
|
// 在实际应用中,可能需要重启应用并请求管理员权限
|
|||
|
|
// 这里我们提供信息给用户
|
|||
|
|
ShowWindowsPermissionDialog();
|
|||
|
|
|
|||
|
|
return false; // 需要用户操作
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"Windows权限请求失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 显示Windows权限说明对话框
|
|||
|
|
/// </summary>
|
|||
|
|
private static void ShowWindowsPermissionDialog()
|
|||
|
|
{
|
|||
|
|
string message = "设置系统时间需要管理员权限。\n\n" +
|
|||
|
|
"请按以下步骤操作:\n" +
|
|||
|
|
"1. 关闭当前应用\n" +
|
|||
|
|
"2. 右键点击应用图标\n" +
|
|||
|
|
"3. 选择'以管理员身份运行'\n" +
|
|||
|
|
"4. 在UAC提示中点击'是'";
|
|||
|
|
|
|||
|
|
Debug.Log($"Windows权限说明: {message}");
|
|||
|
|
|
|||
|
|
// 在实际应用中,这里应该显示一个UI对话框
|
|||
|
|
// 目前只在控制台输出
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 检查Android平台时间设置权限
|
|||
|
|
/// </summary>
|
|||
|
|
private static bool CheckAndroidTimePermission()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// Android 4.2+ 普通应用无法设置系统时间
|
|||
|
|
// 只有系统应用或具有WRITE_SECURE_SETTINGS权限的应用才行
|
|||
|
|
|
|||
|
|
using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
|
|||
|
|
using (var currentActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity"))
|
|||
|
|
using (var packageManager = currentActivity.Call<AndroidJavaObject>("getPackageManager"))
|
|||
|
|
{
|
|||
|
|
string packageName = currentActivity.Call<string>("getPackageName");
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 检查是否有WRITE_SECURE_SETTINGS权限
|
|||
|
|
int permission = packageManager.Call<int>("checkPermission",
|
|||
|
|
"android.permission.WRITE_SECURE_SETTINGS", packageName);
|
|||
|
|
|
|||
|
|
bool hasPermission = permission == 0; // PackageManager.PERMISSION_GRANTED = 0
|
|||
|
|
|
|||
|
|
if (hasPermission)
|
|||
|
|
{
|
|||
|
|
Debug.Log("Android: 应用具有WRITE_SECURE_SETTINGS权限,可以设置系统时间");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("Android: 应用缺少WRITE_SECURE_SETTINGS权限,无法直接设置系统时间");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return hasPermission;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"Android权限检查失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"Android时间权限检查失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 请求Android时间设置权限(实际上是引导用户)
|
|||
|
|
/// </summary>
|
|||
|
|
private static bool RequestAndroidTimePermission()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (CheckAndroidTimePermission())
|
|||
|
|
{
|
|||
|
|
return true; // 已有权限
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.Log("Android: 引导用户到系统设置修改时间");
|
|||
|
|
|
|||
|
|
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.DATE_SETTINGS");
|
|||
|
|
|
|||
|
|
currentActivity.Call("startActivity", intent);
|
|||
|
|
|
|||
|
|
Debug.Log("Android: 已打开系统日期时间设置页面");
|
|||
|
|
|
|||
|
|
// 显示用户操作指南
|
|||
|
|
ShowAndroidTimeSettingGuide();
|
|||
|
|
|
|||
|
|
return false; // 需要用户手动设置
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"Android时间权限请求失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 显示Android时间设置指南
|
|||
|
|
/// </summary>
|
|||
|
|
private static void ShowAndroidTimeSettingGuide()
|
|||
|
|
{
|
|||
|
|
string message = "由于Android系统限制,普通应用无法直接修改系统时间。\n\n" +
|
|||
|
|
"请在弹出的系统设置页面中:\n" +
|
|||
|
|
"1. 关闭'自动确定日期和时间'\n" +
|
|||
|
|
"2. 点击'设置日期'或'设置时间'\n" +
|
|||
|
|
"3. 手动设置所需的日期和时间\n" +
|
|||
|
|
"4. 返回应用继续操作";
|
|||
|
|
|
|||
|
|
Debug.Log($"Android时间设置指南: {message}");
|
|||
|
|
|
|||
|
|
// 在实际应用中,这里应该显示一个UI对话框或提示
|
|||
|
|
// 目前只在控制台输出
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 验证时间设置是否成功
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="targetTime">目标时间</param>
|
|||
|
|
/// <param name="toleranceSeconds">允许的误差秒数</param>
|
|||
|
|
/// <returns>是否设置成功</returns>
|
|||
|
|
public static bool VerifyTimeSet(DateTime targetTime, int toleranceSeconds = 30)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
DateTime currentTime = WindowsSystemController.GetSystemTime();
|
|||
|
|
TimeSpan difference = Math.Abs((currentTime - targetTime).TotalSeconds) > toleranceSeconds ?
|
|||
|
|
currentTime - targetTime : TimeSpan.Zero;
|
|||
|
|
|
|||
|
|
bool success = Math.Abs(difference.TotalSeconds) <= toleranceSeconds;
|
|||
|
|
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"时间设置验证成功: 目标={targetTime:HH:mm:ss}, 当前={currentTime:HH:mm:ss}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"时间设置验证失败: 目标={targetTime:HH:mm:ss}, 当前={currentTime:HH:mm:ss}, 差异={difference.TotalSeconds:F1}秒");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return success;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"时间设置验证失败: {ex.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取推荐的时间设置流程
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns>流程描述</returns>
|
|||
|
|
public static string GetRecommendedTimeSetupProcess()
|
|||
|
|
{
|
|||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|||
|
|
return "Windows平台推荐流程:\n" +
|
|||
|
|
"1. 以管理员身份运行应用\n" +
|
|||
|
|
"2. 在应用中设置时间\n" +
|
|||
|
|
"3. 系统会自动应用新时间";
|
|||
|
|
|
|||
|
|
#elif UNITY_ANDROID && !UNITY_EDITOR
|
|||
|
|
return "Android平台推荐流程:\n" +
|
|||
|
|
"1. 在应用中点击时间设置\n" +
|
|||
|
|
"2. 系统会自动打开设置页面\n" +
|
|||
|
|
"3. 手动设置日期和时间\n" +
|
|||
|
|
"4. 返回应用验证设置";
|
|||
|
|
|
|||
|
|
#else
|
|||
|
|
return "开发模式:可直接设置时间,无需特殊流程";
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|