902 lines
30 KiB
C#
902 lines
30 KiB
C#
using System;
|
||
using System.Runtime.InteropServices;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 跨平台系统控制器
|
||
/// 提供亮度、音量等系统级功能的真实控制
|
||
/// 支持 Windows、Android 等平台
|
||
/// </summary>
|
||
public static class WindowsSystemController
|
||
{
|
||
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
|
||
#region Windows API 声明
|
||
|
||
// 音量控制 API
|
||
[DllImport("user32.dll")]
|
||
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
|
||
|
||
[DllImport("user32.dll")]
|
||
private static extern byte MapVirtualKey(uint uCode, uint uMapType);
|
||
|
||
// 亮度控制 API
|
||
[DllImport("dxva2.dll", SetLastError = true)]
|
||
private static extern bool SetMonitorBrightness(IntPtr hMonitor, uint dwNewBrightness);
|
||
|
||
[DllImport("dxva2.dll", SetLastError = true)]
|
||
private static extern bool GetMonitorBrightness(IntPtr hMonitor, ref uint pdwMinimumBrightness, ref uint pdwCurrentBrightness, ref uint pdwMaximumBrightness);
|
||
|
||
[DllImport("dxva2.dll", SetLastError = true)]
|
||
private static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, ref uint pdwNumberOfPhysicalMonitors);
|
||
|
||
[DllImport("dxva2.dll", SetLastError = true)]
|
||
private static extern bool GetPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, uint dwPhysicalMonitorArraySize, [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray);
|
||
|
||
[DllImport("user32.dll")]
|
||
private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
|
||
|
||
[DllImport("dxva2.dll", SetLastError = true)]
|
||
private static extern bool DestroyPhysicalMonitors(uint dwPhysicalMonitorArraySize, [In] PHYSICAL_MONITOR[] pPhysicalMonitorArray);
|
||
|
||
// WMI 相关 API (备用亮度控制方案)
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern IntPtr LoadLibrary(string lpFileName);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern bool FreeLibrary(IntPtr hModule);
|
||
|
||
// 时间设置 API
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern bool SetSystemTime(ref SYSTEMTIME lpSystemTime);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern void GetSystemTime(out SYSTEMTIME lpSystemTime);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern bool SetLocalTime(ref SYSTEMTIME lpSystemTime);
|
||
|
||
[DllImport("kernel32.dll", SetLastError = true)]
|
||
private static extern void GetLocalTime(out SYSTEMTIME lpSystemTime);
|
||
|
||
#endregion
|
||
|
||
#region 常量定义
|
||
|
||
// 音量控制常量
|
||
private const byte VK_VOLUME_MUTE = 0xAD;
|
||
private const byte VK_VOLUME_DOWN = 0xAE;
|
||
private const byte VK_VOLUME_UP = 0xAF;
|
||
private const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
|
||
private const uint KEYEVENTF_KEYUP = 0x0002;
|
||
|
||
#endregion
|
||
|
||
#region 结构体定义
|
||
|
||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||
public struct PHYSICAL_MONITOR
|
||
{
|
||
public IntPtr hPhysicalMonitor;
|
||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||
public string szPhysicalMonitorDescription;
|
||
}
|
||
|
||
private delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData);
|
||
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
public struct Rect
|
||
{
|
||
public int left;
|
||
public int top;
|
||
public int right;
|
||
public int bottom;
|
||
}
|
||
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
public struct SYSTEMTIME
|
||
{
|
||
public ushort wYear;
|
||
public ushort wMonth;
|
||
public ushort wDayOfWeek;
|
||
public ushort wDay;
|
||
public ushort wHour;
|
||
public ushort wMinute;
|
||
public ushort wSecond;
|
||
public ushort wMilliseconds;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 音量控制
|
||
|
||
/// <summary>
|
||
/// 设置系统音量到指定百分比
|
||
/// </summary>
|
||
/// <param name="volumePercent">音量百分比 (0-100)</param>
|
||
public static bool SetSystemVolume(int volumePercent)
|
||
{
|
||
try
|
||
{
|
||
// 获取当前音量
|
||
int currentVolume = GetCurrentSystemVolume();
|
||
if (currentVolume == -1) return false;
|
||
|
||
int targetVolume = Mathf.Clamp(volumePercent, 0, 100);
|
||
int difference = targetVolume - currentVolume;
|
||
|
||
// 根据差值调整音量
|
||
if (difference > 0)
|
||
{
|
||
for (int i = 0; i < Math.Abs(difference); i += 2) // 每次大约调整2%
|
||
{
|
||
SystemVolumeUp();
|
||
System.Threading.Thread.Sleep(10); // 短暂延时确保命令执行
|
||
}
|
||
}
|
||
else if (difference < 0)
|
||
{
|
||
for (int i = 0; i < Math.Abs(difference); i += 2) // 每次大约调整2%
|
||
{
|
||
SystemVolumeDown();
|
||
System.Threading.Thread.Sleep(10); // 短暂延时确保命令执行
|
||
}
|
||
}
|
||
|
||
Debug.Log($"WindowsSystemController: 音量已设置为 {targetVolume}%");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"WindowsSystemController: 设置音量失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 增加系统音量
|
||
/// </summary>
|
||
public static void SystemVolumeUp()
|
||
{
|
||
keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY, 0);
|
||
keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 降低系统音量
|
||
/// </summary>
|
||
public static void SystemVolumeDown()
|
||
{
|
||
keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY, 0);
|
||
keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换系统静音状态
|
||
/// </summary>
|
||
public static void SystemMute()
|
||
{
|
||
keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY, 0);
|
||
keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前系统音量 (简化估算,实际实现可能需要更复杂的 API)
|
||
/// </summary>
|
||
private static int GetCurrentSystemVolume()
|
||
{
|
||
// 这是一个简化版本,实际实现需要使用 Windows Volume API
|
||
// 目前返回 -1 表示无法获取,使用相对调整
|
||
return -1;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 亮度控制
|
||
|
||
/// <summary>
|
||
/// 设置显示器亮度
|
||
/// </summary>
|
||
/// <param name="brightnessPercent">亮度百分比 (0-100)</param>
|
||
public static bool SetMonitorBrightness(int brightnessPercent)
|
||
{
|
||
try
|
||
{
|
||
uint brightness = (uint)Mathf.Clamp(brightnessPercent, 0, 100);
|
||
|
||
// 方法1: 尝试使用 DXVA2 API
|
||
if (SetBrightnessViaDDC(brightness))
|
||
{
|
||
Debug.Log($"WindowsSystemController: 亮度已通过DDC设置为 {brightness}%");
|
||
return true;
|
||
}
|
||
|
||
// 方法2: 尝试使用 WMI (需要管理员权限)
|
||
if (SetBrightnessViaWMI(brightness))
|
||
{
|
||
Debug.Log($"WindowsSystemController: 亮度已通过WMI设置为 {brightness}%");
|
||
return true;
|
||
}
|
||
|
||
// 方法3: 使用 PowerShell 命令 (备用方案)
|
||
if (SetBrightnessViaPowerShell(brightness))
|
||
{
|
||
Debug.Log($"WindowsSystemController: 亮度已通过PowerShell设置为 {brightness}%");
|
||
return true;
|
||
}
|
||
|
||
Debug.LogWarning("WindowsSystemController: 所有亮度控制方法都失败了");
|
||
return false;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"WindowsSystemController: 设置亮度失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过 DDC/CI 设置亮度 (外接显示器)
|
||
/// </summary>
|
||
private static bool SetBrightnessViaDDC(uint brightness)
|
||
{
|
||
try
|
||
{
|
||
bool success = false;
|
||
EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, (IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData) =>
|
||
{
|
||
uint numPhysicalMonitors = 0;
|
||
if (GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, ref numPhysicalMonitors) && numPhysicalMonitors > 0)
|
||
{
|
||
PHYSICAL_MONITOR[] physicalMonitors = new PHYSICAL_MONITOR[numPhysicalMonitors];
|
||
|
||
if (GetPhysicalMonitorsFromHMONITOR(hMonitor, numPhysicalMonitors, physicalMonitors))
|
||
{
|
||
for (uint i = 0; i < numPhysicalMonitors; i++)
|
||
{
|
||
if (SetMonitorBrightness(physicalMonitors[i].hPhysicalMonitor, brightness))
|
||
{
|
||
success = true;
|
||
Debug.Log($"成功设置显示器 {physicalMonitors[i].szPhysicalMonitorDescription} 亮度为 {brightness}%");
|
||
}
|
||
}
|
||
|
||
DestroyPhysicalMonitors(numPhysicalMonitors, physicalMonitors);
|
||
}
|
||
}
|
||
return true; // 继续枚举
|
||
}, IntPtr.Zero);
|
||
|
||
return success;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"DDC亮度控制失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过 WMI 设置亮度 (笔记本内置屏幕)
|
||
/// </summary>
|
||
private static bool SetBrightnessViaWMI(uint brightness)
|
||
{
|
||
try
|
||
{
|
||
// 使用 WMI 设置亮度 (需要 System.Management 或者 PowerShell)
|
||
// 这里使用简化的 PowerShell 调用方式
|
||
string script = $"(Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,{brightness})";
|
||
return ExecutePowerShellCommand(script);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"WMI亮度控制失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过 PowerShell 设置亮度
|
||
/// </summary>
|
||
private static bool SetBrightnessViaPowerShell(uint brightness)
|
||
{
|
||
try
|
||
{
|
||
// 使用 Windows 10/11 的现代亮度控制
|
||
string script = $@"
|
||
Add-Type -AssemblyName System.Windows.Forms
|
||
$brightness = {brightness}
|
||
try {{
|
||
(Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,$brightness)
|
||
exit 0
|
||
}} catch {{
|
||
exit 1
|
||
}}
|
||
";
|
||
|
||
return ExecutePowerShellCommand(script);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"PowerShell亮度控制失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行 PowerShell 命令
|
||
/// </summary>
|
||
private static bool ExecutePowerShellCommand(string script)
|
||
{
|
||
try
|
||
{
|
||
var processInfo = new System.Diagnostics.ProcessStartInfo
|
||
{
|
||
FileName = "powershell.exe",
|
||
Arguments = $"-Command \"{script}\"",
|
||
UseShellExecute = false,
|
||
CreateNoWindow = true,
|
||
RedirectStandardOutput = true,
|
||
RedirectStandardError = true
|
||
};
|
||
|
||
using (var process = System.Diagnostics.Process.Start(processInfo))
|
||
{
|
||
process.WaitForExit(5000); // 5秒超时
|
||
return process.ExitCode == 0;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"PowerShell执行失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||
|
||
#region Android 实现
|
||
|
||
private static AndroidJavaClass _unityPlayer;
|
||
private static AndroidJavaObject _currentActivity;
|
||
private static AndroidJavaObject _audioManager;
|
||
|
||
/// <summary>
|
||
/// 初始化Android系统控制
|
||
/// </summary>
|
||
static WindowsSystemController()
|
||
{
|
||
try
|
||
{
|
||
_unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
||
_currentActivity = _unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
|
||
|
||
// 获取AudioManager
|
||
_audioManager = _currentActivity.Call<AndroidJavaObject>("getSystemService", "audio");
|
||
|
||
Debug.Log("Android系统控制器初始化成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android系统控制器初始化失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置Android系统音量
|
||
/// </summary>
|
||
public static bool SetSystemVolume(int volumePercent)
|
||
{
|
||
try
|
||
{
|
||
if (_audioManager == null) return false;
|
||
|
||
// 获取最大音量
|
||
int maxVolume = _audioManager.Call<int>("getStreamMaxVolume", 3); // STREAM_MUSIC = 3
|
||
|
||
// 计算目标音量
|
||
int targetVolume = Mathf.RoundToInt((volumePercent / 100f) * maxVolume);
|
||
targetVolume = Mathf.Clamp(targetVolume, 0, maxVolume);
|
||
|
||
// 设置音量
|
||
_audioManager.Call("setStreamVolume", 3, targetVolume, 0); // FLAG_SHOW_UI = 1, 不显示UI = 0
|
||
|
||
Debug.Log($"Android: 音量已设置为 {volumePercent}% (系统值: {targetVolume}/{maxVolume})");
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android音量设置失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 增加Android系统音量
|
||
/// </summary>
|
||
public static void SystemVolumeUp()
|
||
{
|
||
try
|
||
{
|
||
if (_audioManager == null) return;
|
||
|
||
_audioManager.Call("adjustStreamVolume", 3, 1, 0); // STREAM_MUSIC, ADJUST_RAISE, no flags
|
||
Debug.Log("Android: 音量增加");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android音量增加失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 降低Android系统音量
|
||
/// </summary>
|
||
public static void SystemVolumeDown()
|
||
{
|
||
try
|
||
{
|
||
if (_audioManager == null) return;
|
||
|
||
_audioManager.Call("adjustStreamVolume", 3, -1, 0); // STREAM_MUSIC, ADJUST_LOWER, no flags
|
||
Debug.Log("Android: 音量降低");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android音量降低失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换Android系统静音
|
||
/// </summary>
|
||
public static void SystemMute()
|
||
{
|
||
try
|
||
{
|
||
if (_audioManager == null) return;
|
||
|
||
// 获取当前音量
|
||
int currentVolume = _audioManager.Call<int>("getStreamVolume", 3);
|
||
|
||
if (currentVolume > 0)
|
||
{
|
||
// 静音
|
||
_audioManager.Call("setStreamVolume", 3, 0, 0);
|
||
Debug.Log("Android: 静音");
|
||
}
|
||
else
|
||
{
|
||
// 恢复到中等音量
|
||
int maxVolume = _audioManager.Call<int>("getStreamMaxVolume", 3);
|
||
_audioManager.Call("setStreamVolume", 3, maxVolume / 2, 0);
|
||
Debug.Log("Android: 恢复音量");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android静音切换失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置Android屏幕亮度
|
||
/// </summary>
|
||
public static bool SetMonitorBrightness(int brightnessPercent)
|
||
{
|
||
try
|
||
{
|
||
if (_currentActivity == null) return false;
|
||
|
||
// Android亮度范围是0-255
|
||
float brightness = Mathf.Clamp01(brightnessPercent / 100f);
|
||
int systemBrightness = Mathf.RoundToInt(brightness * 255f);
|
||
|
||
// 方法1: 设置当前窗口亮度 (仅对当前应用生效)
|
||
AndroidJavaObject window = _currentActivity.Call<AndroidJavaObject>("getWindow");
|
||
AndroidJavaObject layoutParams = window.Call<AndroidJavaObject>("getAttributes");
|
||
|
||
layoutParams.Set("screenBrightness", brightness); // 0.0f - 1.0f
|
||
window.Call("setAttributes", layoutParams);
|
||
|
||
Debug.Log($"Android: 应用窗口亮度已设置为 {brightnessPercent}%");
|
||
|
||
// 方法2: 尝试设置系统亮度 (需要WRITE_SETTINGS权限)
|
||
try
|
||
{
|
||
AndroidJavaClass settingsSystem = new AndroidJavaClass("android.provider.Settings$System");
|
||
AndroidJavaObject contentResolver = _currentActivity.Call<AndroidJavaObject>("getContentResolver");
|
||
|
||
bool success = settingsSystem.CallStatic<bool>("putInt",
|
||
contentResolver,
|
||
"screen_brightness",
|
||
systemBrightness);
|
||
|
||
if (success)
|
||
{
|
||
Debug.Log($"Android: 系统亮度已设置为 {brightnessPercent}%");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Android: 系统亮度设置失败,可能缺少WRITE_SETTINGS权限");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogWarning($"Android系统亮度设置失败 (权限问题): {ex.Message}");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android亮度设置失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前Android音量
|
||
/// </summary>
|
||
public static int GetCurrentVolume()
|
||
{
|
||
try
|
||
{
|
||
if (_audioManager == null) return -1;
|
||
|
||
int currentVolume = _audioManager.Call<int>("getStreamVolume", 3);
|
||
int maxVolume = _audioManager.Call<int>("getStreamMaxVolume", 3);
|
||
|
||
return Mathf.RoundToInt((currentVolume / (float)maxVolume) * 100f);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"获取Android音量失败: {ex.Message}");
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前Android亮度
|
||
/// </summary>
|
||
public static int GetCurrentBrightness()
|
||
{
|
||
try
|
||
{
|
||
if (_currentActivity == null) return -1;
|
||
|
||
AndroidJavaClass settingsSystem = new AndroidJavaClass("android.provider.Settings$System");
|
||
AndroidJavaObject contentResolver = _currentActivity.Call<AndroidJavaObject>("getContentResolver");
|
||
|
||
int brightness = settingsSystem.CallStatic<int>("getInt",
|
||
contentResolver,
|
||
"screen_brightness",
|
||
128); // 默认值
|
||
|
||
return Mathf.RoundToInt((brightness / 255f) * 100f);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"获取Android亮度失败: {ex.Message}");
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 时间控制
|
||
|
||
/// <summary>
|
||
/// 设置系统时间 - 跨平台实现
|
||
/// </summary>
|
||
/// <param name="dateTime">要设置的时间</param>
|
||
/// <returns>设置是否成功</returns>
|
||
public static bool SetSystemTime(DateTime dateTime)
|
||
{
|
||
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
return SetWindowsSystemTime(dateTime);
|
||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||
return SetAndroidSystemTime(dateTime);
|
||
#else
|
||
Debug.Log($"[模拟] 系统时间设置为: {dateTime:yyyy-MM-dd HH:mm:ss}");
|
||
return true;
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前系统时间 - 跨平台实现
|
||
/// </summary>
|
||
/// <returns>当前系统时间</returns>
|
||
public static DateTime GetSystemTime()
|
||
{
|
||
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
return GetWindowsSystemTime();
|
||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||
return GetAndroidSystemTime();
|
||
#else
|
||
return DateTime.Now;
|
||
#endif
|
||
}
|
||
|
||
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
|
||
/// <summary>
|
||
/// Windows平台设置系统时间
|
||
/// 注意:需要管理员权限
|
||
/// </summary>
|
||
private static bool SetWindowsSystemTime(DateTime dateTime)
|
||
{
|
||
try
|
||
{
|
||
SYSTEMTIME st = new SYSTEMTIME
|
||
{
|
||
wYear = (ushort)dateTime.Year,
|
||
wMonth = (ushort)dateTime.Month,
|
||
wDayOfWeek = (ushort)dateTime.DayOfWeek,
|
||
wDay = (ushort)dateTime.Day,
|
||
wHour = (ushort)dateTime.Hour,
|
||
wMinute = (ushort)dateTime.Minute,
|
||
wSecond = (ushort)dateTime.Second,
|
||
wMilliseconds = (ushort)dateTime.Millisecond
|
||
};
|
||
|
||
bool result = SetLocalTime(ref st);
|
||
|
||
if (result)
|
||
{
|
||
Debug.Log($"Windows: 系统时间已设置为 {dateTime:yyyy-MM-dd HH:mm:ss}");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Windows: 设置系统时间失败,可能需要管理员权限");
|
||
|
||
// 尝试使用命令行方式
|
||
return SetWindowsSystemTimeViaCommand(dateTime);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Windows系统时间设置失败: {ex.Message}");
|
||
return SetWindowsSystemTimeViaCommand(dateTime);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过命令行设置Windows系统时间
|
||
/// </summary>
|
||
private static bool SetWindowsSystemTimeViaCommand(DateTime dateTime)
|
||
{
|
||
try
|
||
{
|
||
string dateCommand = $"date {dateTime:MM-dd-yyyy}";
|
||
string timeCommand = $"time {dateTime:HH:mm:ss}";
|
||
|
||
var processDate = new System.Diagnostics.Process
|
||
{
|
||
StartInfo = new System.Diagnostics.ProcessStartInfo
|
||
{
|
||
FileName = "cmd.exe",
|
||
Arguments = $"/C {dateCommand}",
|
||
UseShellExecute = false,
|
||
CreateNoWindow = true,
|
||
Verb = "runas" // 以管理员身份运行
|
||
}
|
||
};
|
||
|
||
var processTime = new System.Diagnostics.Process
|
||
{
|
||
StartInfo = new System.Diagnostics.ProcessStartInfo
|
||
{
|
||
FileName = "cmd.exe",
|
||
Arguments = $"/C {timeCommand}",
|
||
UseShellExecute = false,
|
||
CreateNoWindow = true,
|
||
Verb = "runas" // 以管理员身份运行
|
||
}
|
||
};
|
||
|
||
bool dateSuccess = processDate.Start() && processDate.WaitForExit(5000);
|
||
bool timeSuccess = processTime.Start() && processTime.WaitForExit(5000);
|
||
|
||
if (dateSuccess && timeSuccess)
|
||
{
|
||
Debug.Log($"Windows: 通过命令行设置系统时间成功 {dateTime:yyyy-MM-dd HH:mm:ss}");
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Windows: 命令行设置系统时间失败,可能被用户拒绝或超时");
|
||
return false;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Windows命令行时间设置失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Windows系统时间
|
||
/// </summary>
|
||
private static DateTime GetWindowsSystemTime()
|
||
{
|
||
try
|
||
{
|
||
GetLocalTime(out SYSTEMTIME st);
|
||
return new DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"获取Windows系统时间失败: {ex.Message}");
|
||
return DateTime.Now;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
|
||
/// <summary>
|
||
/// Android平台设置系统时间
|
||
/// 注意:需要WRITE_SECURE_SETTINGS权限,通常只有系统应用才能获得
|
||
/// </summary>
|
||
private static bool SetAndroidSystemTime(DateTime dateTime)
|
||
{
|
||
try
|
||
{
|
||
using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
|
||
using (var currentActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity"))
|
||
using (var contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver"))
|
||
{
|
||
// Android系统时间是以毫秒为单位的时间戳
|
||
long timeMillis = ((DateTimeOffset)dateTime).ToUnixTimeMilliseconds();
|
||
|
||
try
|
||
{
|
||
// 尝试设置系统时间 (需要系统权限)
|
||
var systemClock = new AndroidJavaClass("android.os.SystemClock");
|
||
bool result = systemClock.CallStatic<bool>("setCurrentTimeMillis", timeMillis);
|
||
|
||
if (result)
|
||
{
|
||
Debug.Log($"Android: 系统时间已设置为 {dateTime:yyyy-MM-dd HH:mm:ss}");
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Android: 设置系统时间失败,可能缺少WRITE_SECURE_SETTINGS权限");
|
||
|
||
// 尝试使用AlarmManager设置(备用方案)
|
||
return SetAndroidTimeViaAlarmManager(currentActivity, dateTime);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogWarning($"Android直接时间设置失败: {ex.Message}");
|
||
return SetAndroidTimeViaAlarmManager(currentActivity, dateTime);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android系统时间设置失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过AlarmManager尝试时间设置(限制较多)
|
||
/// </summary>
|
||
private static bool SetAndroidTimeViaAlarmManager(AndroidJavaObject activity, DateTime dateTime)
|
||
{
|
||
try
|
||
{
|
||
// 注意:从Android 4.2开始,普通应用无法直接修改系统时间
|
||
// 这里只能提供用户引导到系统设置页面
|
||
|
||
Debug.LogWarning("Android: 普通应用无法直接修改系统时间,将引导用户到系统设置");
|
||
|
||
// 打开系统日期时间设置页面
|
||
var intent = new AndroidJavaObject("android.content.Intent");
|
||
intent.Call<AndroidJavaObject>("setAction", "android.settings.DATE_SETTINGS");
|
||
|
||
activity.Call("startActivity", intent);
|
||
|
||
Debug.Log("Android: 已打开系统日期时间设置页面");
|
||
return false; // 返回false表示需要用户手动设置
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"Android时间设置引导失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Android系统时间
|
||
/// </summary>
|
||
private static DateTime GetAndroidSystemTime()
|
||
{
|
||
try
|
||
{
|
||
var systemClass = new AndroidJavaClass("java.lang.System");
|
||
long timeMillis = systemClass.CallStatic<long>("currentTimeMillis");
|
||
|
||
DateTime dateTime = DateTimeOffset.FromUnixTimeMilliseconds(timeMillis).DateTime;
|
||
return dateTime;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"获取Android系统时间失败: {ex.Message}");
|
||
return DateTime.Now;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
#endregion
|
||
|
||
#else
|
||
|
||
// 其他平台或编辑器模式的模拟实现
|
||
public static bool SetSystemVolume(int volumePercent)
|
||
{
|
||
Debug.Log($"[模拟] 音量设置为: {volumePercent}%");
|
||
return true;
|
||
}
|
||
|
||
public static void SystemVolumeUp()
|
||
{
|
||
Debug.Log("[模拟] 音量增加");
|
||
}
|
||
|
||
public static void SystemVolumeDown()
|
||
{
|
||
Debug.Log("[模拟] 音量减少");
|
||
}
|
||
|
||
public static void SystemMute()
|
||
{
|
||
Debug.Log("[模拟] 静音切换");
|
||
}
|
||
|
||
public static bool SetMonitorBrightness(int brightnessPercent)
|
||
{
|
||
Debug.Log($"[模拟] 亮度设置为: {brightnessPercent}%");
|
||
return true;
|
||
}
|
||
|
||
public static int GetCurrentVolume()
|
||
{
|
||
Debug.Log("[模拟] 获取当前音量");
|
||
return 50; // 模拟返回50%
|
||
}
|
||
|
||
public static int GetCurrentBrightness()
|
||
{
|
||
Debug.Log("[模拟] 获取当前亮度");
|
||
return 70; // 模拟返回70%
|
||
}
|
||
|
||
public static bool SetSystemTime(DateTime dateTime)
|
||
{
|
||
Debug.Log($"[模拟] 系统时间设置为: {dateTime:yyyy-MM-dd HH:mm:ss}");
|
||
return true;
|
||
}
|
||
|
||
public static DateTime GetSystemTime()
|
||
{
|
||
Debug.Log("[模拟] 获取系统时间");
|
||
return DateTime.Now;
|
||
}
|
||
|
||
#endif
|
||
} |