425 lines
15 KiB
C#
425 lines
15 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Android 网络配置器
|
|||
|
|
/// 使用 Java 反射调用 Android WifiManager 和 DhcpInfo API 实现 DHCP/静态IP配置
|
|||
|
|
/// 需要权限: android.permission.CHANGE_NETWORK_STATE, android.permission.ACCESS_WIFI_STATE, android.permission.CHANGE_WIFI_STATE
|
|||
|
|
/// </summary>
|
|||
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|||
|
|
public static class AndroidNetworkConfigurator
|
|||
|
|
{
|
|||
|
|
private static AndroidJavaObject _wifiManager;
|
|||
|
|
private static AndroidJavaObject _connectivityManager;
|
|||
|
|
private static AndroidJavaObject _currentActivity;
|
|||
|
|
private static AndroidJavaClass _unityPlayer;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 初始化 Android 网络管理对象
|
|||
|
|
/// </summary>
|
|||
|
|
private static void Initialize()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (_wifiManager != null) return;
|
|||
|
|
|
|||
|
|
_unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
|||
|
|
_currentActivity = _unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
|
|||
|
|
|
|||
|
|
AndroidJavaObject context = _currentActivity.Call<AndroidJavaObject>("getApplicationContext");
|
|||
|
|
_wifiManager = context.Call<AndroidJavaObject>("getSystemService", "wifi");
|
|||
|
|
_connectivityManager = context.Call<AndroidJavaObject>("getSystemService", "connectivity");
|
|||
|
|
|
|||
|
|
Debug.Log("[AndroidNetworkConfigurator] 初始化成功");
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 初始化失败: {ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 应用 DHCP 配置
|
|||
|
|
/// </summary>
|
|||
|
|
public static bool ApplyDhcp()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Initialize();
|
|||
|
|
|
|||
|
|
if (_wifiManager == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[AndroidNetworkConfigurator] WifiManager 为空,无法应用 DHCP");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取 WifiManager.DhcpInfo
|
|||
|
|
AndroidJavaObject dhcpInfo = _wifiManager.Call<AndroidJavaObject>("getDhcpInfo");
|
|||
|
|
|
|||
|
|
if (dhcpInfo == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("[AndroidNetworkConfigurator] 无法获取 DhcpInfo");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取 WifiConfiguration
|
|||
|
|
AndroidJavaObject wifiConfig = GetCurrentWifiConfiguration();
|
|||
|
|
if (wifiConfig == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[AndroidNetworkConfigurator] 无法获取当前 WiFi 配置");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清除静态IP配置,启用DHCP
|
|||
|
|
AndroidJavaClass ipAssignmentClass = new AndroidJavaClass("android.net.wifi.WifiConfiguration$IpAssignment");
|
|||
|
|
AndroidJavaObject dhcpAssignment = ipAssignmentClass.GetStatic<AndroidJavaObject>("DHCP");
|
|||
|
|
|
|||
|
|
wifiConfig.Set("ipAssignment", dhcpAssignment);
|
|||
|
|
|
|||
|
|
// 保存 WiFi 配置
|
|||
|
|
int networkId = _wifiManager.Call<int>("addNetwork", wifiConfig);
|
|||
|
|
if (networkId == -1)
|
|||
|
|
{
|
|||
|
|
// 尝试更新已有配置
|
|||
|
|
networkId = wifiConfig.Get<int>("networkId");
|
|||
|
|
_wifiManager.Call<bool>("updateNetwork", wifiConfig);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool success = _wifiManager.Call<bool>("enableNetwork", networkId, true);
|
|||
|
|
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[AndroidNetworkConfigurator] DHCP 配置已应用,NetworkId: {networkId}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[AndroidNetworkConfigurator] DHCP 配置应用失败");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return success;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 应用 DHCP 异常: {ex.Message}\n{ex.StackTrace}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 应用静态 IP 配置
|
|||
|
|
/// </summary>
|
|||
|
|
public static bool ApplyStaticIP(string ipAddress, string netmask, string gateway, string dns1, string dns2 = null)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Initialize();
|
|||
|
|
|
|||
|
|
if (_wifiManager == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[AndroidNetworkConfigurator] WifiManager 为空,无法应用静态 IP");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (string.IsNullOrWhiteSpace(ipAddress) || string.IsNullOrWhiteSpace(netmask))
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[AndroidNetworkConfigurator] IP 或子网掩码不能为空");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取当前 WiFi 配置
|
|||
|
|
AndroidJavaObject wifiConfig = GetCurrentWifiConfiguration();
|
|||
|
|
if (wifiConfig == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[AndroidNetworkConfigurator] 无法获取当前 WiFi 配置");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置IP分配方式为静态
|
|||
|
|
AndroidJavaClass ipAssignmentClass = new AndroidJavaClass("android.net.wifi.WifiConfiguration$IpAssignment");
|
|||
|
|
AndroidJavaObject staticAssignment = ipAssignmentClass.GetStatic<AndroidJavaObject>("STATIC");
|
|||
|
|
wifiConfig.Set("ipAssignment", staticAssignment);
|
|||
|
|
|
|||
|
|
// 创建 StaticIpConfiguration 对象
|
|||
|
|
AndroidJavaObject staticIpConfig = CreateStaticIpConfiguration(ipAddress, netmask, gateway, dns1, dns2);
|
|||
|
|
wifiConfig.Set("staticIpConfiguration", staticIpConfig);
|
|||
|
|
|
|||
|
|
// 保存 WiFi 配置
|
|||
|
|
int networkId = _wifiManager.Call<int>("addNetwork", wifiConfig);
|
|||
|
|
if (networkId == -1)
|
|||
|
|
{
|
|||
|
|
networkId = wifiConfig.Get<int>("networkId");
|
|||
|
|
_wifiManager.Call<bool>("updateNetwork", wifiConfig);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool success = _wifiManager.Call<bool>("enableNetwork", networkId, true);
|
|||
|
|
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[AndroidNetworkConfigurator] 静态 IP 配置已应用\n" +
|
|||
|
|
$" IP: {ipAddress}\n" +
|
|||
|
|
$" Mask: {netmask}\n" +
|
|||
|
|
$" Gateway: {gateway}\n" +
|
|||
|
|
$" DNS1: {dns1}\n" +
|
|||
|
|
$" DNS2: {(dns2 ?? "无")}\n" +
|
|||
|
|
$" NetworkId: {networkId}");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[AndroidNetworkConfigurator] 静态 IP 配置应用失败");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return success;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 应用静态 IP 异常: {ex.Message}\n{ex.StackTrace}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取当前连接的 WiFi 配置
|
|||
|
|
/// </summary>
|
|||
|
|
private static AndroidJavaObject GetCurrentWifiConfiguration()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 获取连接信息
|
|||
|
|
AndroidJavaObject connectionInfo = _wifiManager.Call<AndroidJavaObject>("getConnectionInfo");
|
|||
|
|
if (connectionInfo == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning("[AndroidNetworkConfigurator] 未连接到任何 WiFi");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int networkId = connectionInfo.Call<int>("getNetworkId");
|
|||
|
|
Debug.Log($"[AndroidNetworkConfigurator] 当前 NetworkId: {networkId}");
|
|||
|
|
|
|||
|
|
// 获取已配置的网络列表
|
|||
|
|
AndroidJavaObject configList = _wifiManager.Call<AndroidJavaObject>("getConfiguredNetworks");
|
|||
|
|
if (configList == null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[AndroidNetworkConfigurator] 无法获取配置列表");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 遍历找到当前连接的配置
|
|||
|
|
AndroidJavaClass listClass = new AndroidJavaClass("java.util.List");
|
|||
|
|
int size = configList.Call<int>("size");
|
|||
|
|
|
|||
|
|
for (int i = 0; i < size; i++)
|
|||
|
|
{
|
|||
|
|
AndroidJavaObject config = configList.Call<AndroidJavaObject>("get", i);
|
|||
|
|
int cfgNetworkId = config.Get<int>("networkId");
|
|||
|
|
|
|||
|
|
if (cfgNetworkId == networkId)
|
|||
|
|
{
|
|||
|
|
return config;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果没找到,创建新的配置
|
|||
|
|
Debug.LogWarning("[AndroidNetworkConfigurator] 未找到现有配置,创建新配置");
|
|||
|
|
AndroidJavaObject newConfig = new AndroidJavaObject("android.net.wifi.WifiConfiguration");
|
|||
|
|
newConfig.Set("networkId", networkId);
|
|||
|
|
return newConfig;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 获取 WiFi 配置异常: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 创建 StaticIpConfiguration 对象
|
|||
|
|
/// </summary>
|
|||
|
|
private static AndroidJavaObject CreateStaticIpConfiguration(string ipAddress, string netmask, string gateway, string dns1, string dns2)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
AndroidJavaObject staticIpConfig = new AndroidJavaObject("android.net.StaticIpConfiguration");
|
|||
|
|
|
|||
|
|
// 设置 IP 地址
|
|||
|
|
AndroidJavaObject ipAddr = CreateInetAddress(ipAddress);
|
|||
|
|
int prefixLength = MaskToPrefixLength(netmask);
|
|||
|
|
AndroidJavaObject linkAddress = new AndroidJavaObject("android.net.LinkAddress", ipAddr, prefixLength);
|
|||
|
|
staticIpConfig.Call("addIpAddress", linkAddress);
|
|||
|
|
|
|||
|
|
// 设置网关
|
|||
|
|
if (!string.IsNullOrWhiteSpace(gateway))
|
|||
|
|
{
|
|||
|
|
AndroidJavaObject gatewayAddr = CreateInetAddress(gateway);
|
|||
|
|
staticIpConfig.Set("gateway", gatewayAddr);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加 DNS 服务器
|
|||
|
|
AndroidJavaClass inetAddressClass = new AndroidJavaClass("java.net.InetAddress");
|
|||
|
|
AndroidJavaObject dnsCollection = staticIpConfig.Get<AndroidJavaObject>("dnsServers");
|
|||
|
|
|
|||
|
|
if (!string.IsNullOrWhiteSpace(dns1))
|
|||
|
|
{
|
|||
|
|
AndroidJavaObject dns1Addr = CreateInetAddress(dns1);
|
|||
|
|
dnsCollection.Call<bool>("add", dns1Addr);
|
|||
|
|
Debug.Log($"[AndroidNetworkConfigurator] 添加 DNS1: {dns1}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!string.IsNullOrWhiteSpace(dns2))
|
|||
|
|
{
|
|||
|
|
AndroidJavaObject dns2Addr = CreateInetAddress(dns2);
|
|||
|
|
dnsCollection.Call<bool>("add", dns2Addr);
|
|||
|
|
Debug.Log($"[AndroidNetworkConfigurator] 添加 DNS2: {dns2}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return staticIpConfig;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 创建 StaticIpConfiguration 异常: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据 IP 地址字符串创建 InetAddress 对象
|
|||
|
|
/// </summary>
|
|||
|
|
private static AndroidJavaObject CreateInetAddress(string ipAddress)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
AndroidJavaClass inetAddressClass = new AndroidJavaClass("java.net.InetAddress");
|
|||
|
|
return inetAddressClass.CallStatic<AndroidJavaObject>("getByName", ipAddress);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 创建 InetAddress '{ipAddress}' 异常: {ex.Message}");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 将子网掩码转换为前缀长度(CIDR)
|
|||
|
|
/// </summary>
|
|||
|
|
private static int MaskToPrefixLength(string netmask)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string[] parts = netmask.Split('.');
|
|||
|
|
if (parts.Length != 4)
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[AndroidNetworkConfigurator] 无效的子网掩码: {netmask}");
|
|||
|
|
return 24; // 默认 /24
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int maskValue = 0;
|
|||
|
|
for (int i = 0; i < 4; i++)
|
|||
|
|
{
|
|||
|
|
if (int.TryParse(parts[i], out int octet))
|
|||
|
|
{
|
|||
|
|
maskValue = (maskValue << 8) | octet;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算前缀长度
|
|||
|
|
int prefixLength = 0;
|
|||
|
|
uint mask = 0x80000000;
|
|||
|
|
for (int i = 0; i < 32; i++)
|
|||
|
|
{
|
|||
|
|
if ((maskValue & mask) == mask)
|
|||
|
|
{
|
|||
|
|
prefixLength++;
|
|||
|
|
mask >>= 1;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Debug.Log($"[AndroidNetworkConfigurator] 子网掩码 {netmask} → 前缀长度 {prefixLength}");
|
|||
|
|
return prefixLength;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 转换掩码异常: {ex.Message}");
|
|||
|
|
return 24;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取当前 IP 配置信息
|
|||
|
|
/// </summary>
|
|||
|
|
public static Dictionary<string, string> GetCurrentIPConfiguration()
|
|||
|
|
{
|
|||
|
|
var config = new Dictionary<string, string>();
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
Initialize();
|
|||
|
|
|
|||
|
|
if (_wifiManager == null)
|
|||
|
|
{
|
|||
|
|
config["status"] = "error";
|
|||
|
|
config["message"] = "WifiManager 为空";
|
|||
|
|
return config;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AndroidJavaObject connectionInfo = _wifiManager.Call<AndroidJavaObject>("getConnectionInfo");
|
|||
|
|
AndroidJavaObject dhcpInfo = _wifiManager.Call<AndroidJavaObject>("getDhcpInfo");
|
|||
|
|
|
|||
|
|
if (connectionInfo != null)
|
|||
|
|
{
|
|||
|
|
int ipInt = connectionInfo.Call<int>("getIpAddress");
|
|||
|
|
string ip = FormatIPAddress(ipInt);
|
|||
|
|
config["current_ip"] = ip;
|
|||
|
|
|
|||
|
|
string ssid = connectionInfo.Call<string>("getSSID");
|
|||
|
|
config["ssid"] = ssid ?? "未知";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (dhcpInfo != null)
|
|||
|
|
{
|
|||
|
|
int ipInt = dhcpInfo.Get<int>("ipAddress");
|
|||
|
|
string ip = FormatIPAddress(ipInt);
|
|||
|
|
config["dhcp_ip"] = ip;
|
|||
|
|
|
|||
|
|
int maskInt = dhcpInfo.Get<int>("netmask");
|
|||
|
|
string mask = FormatIPAddress(maskInt);
|
|||
|
|
config["dhcp_mask"] = mask;
|
|||
|
|
|
|||
|
|
int gatewayInt = dhcpInfo.Get<int>("gateway");
|
|||
|
|
string gateway = FormatIPAddress(gatewayInt);
|
|||
|
|
config["dhcp_gateway"] = gateway;
|
|||
|
|
|
|||
|
|
int dns1Int = dhcpInfo.Get<int>("dns1");
|
|||
|
|
string dns1 = FormatIPAddress(dns1Int);
|
|||
|
|
config["dhcp_dns1"] = dns1;
|
|||
|
|
|
|||
|
|
int dns2Int = dhcpInfo.Get<int>("dns2");
|
|||
|
|
string dns2 = FormatIPAddress(dns2Int);
|
|||
|
|
config["dhcp_dns2"] = dns2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
config["status"] = "success";
|
|||
|
|
return config;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
config["status"] = "error";
|
|||
|
|
config["message"] = ex.Message;
|
|||
|
|
Debug.LogError($"[AndroidNetworkConfigurator] 获取 IP 配置异常: {ex.Message}");
|
|||
|
|
return config;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 格式化整数 IP 地址为点分十进制
|
|||
|
|
/// </summary>
|
|||
|
|
private static string FormatIPAddress(int ipInt)
|
|||
|
|
{
|
|||
|
|
return $"{(ipInt & 0xff)}.{((ipInt >> 8) & 0xff)}.{((ipInt >> 16) & 0xff)}.{((ipInt >> 24) & 0xff)}";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif
|