@hide EthernetManager
通过 android.net.EthernetManager#setConfiguration 可以设置以太网 IP 信息,可惜 EthernetManager 无法直接调用。
/**
* A class representing the IP configuration of the Ethernet network.
*
* @hide
*/
public class EthernetManager {
...
/**
* Set Ethernet configuration.
*/
public void setConfiguration(IpConfiguration config) {
try {
mService.setConfiguration(config);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
...
}
反射调用 setConfiguration 方法
DHCP 配置
步骤:
- 实例化 IpConfiguration() 对象 ipConfiguration
- 设置 ipConfiguration.ipConfiguration = xxx
- 设置 ipConfiguration.ipConfiguration = xxx
- 调用 ethernetManager.setConfiguration(ipConfiguration) 完成设置
/**
* 调用 EthernetManager.setConfiguration(IpConfiguration config) 设置 DHCP
*
* 步骤:
* - 实例化 IpConfiguration() 对象 ipConfiguration
* - 设置 ipConfiguration.ipConfiguration = xxx
* - 设置 ipConfiguration.ipConfiguration = xxx
* - 调用 ethernetManager.setConfiguration(ipConfiguration) 完成设置
*/
@WorkerThread
fun setDynamicIp(ethernetManager: EthernetManager): Boolean {
try {
// 获取 IpConfiguration 对象
val ipConfigurationCls = Class.forName("android.net.IpConfiguration")
val ipConfigurationEnum = getEnumMap(ipConfigurationCls)
val ipConfiguration = ipConfigurationCls.newInstance()
// 设置 ipConfiguration.ipAssignment 为 IpAssignment.DHCP
val ipAssignment = ipConfigurationCls.getField("ipAssignment")
ipAssignment.set(ipConfiguration, ipConfigurationEnum["IpAssignment.DHCP"])
// 设置 ipConfiguration.proxySettings 为 ProxySettings.NONE
val proxySettings = ipConfigurationCls.getField("proxySettings")
proxySettings.set(ipConfiguration, ipConfigurationEnum["ProxySettings.NONE"])
// 调用 ethernetManager.setConfiguration(ipConfiguration) 设置 DHCP
val setConfigurationMethod = ethernetManager.javaClass.getDeclaredMethod(
"setConfiguration", ipConfiguration.javaClass
)
setConfigurationMethod.invoke(ethernetManager, ipConfiguration)
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
/**
* 获取 Class 中枚举类键值对
*
* 注:key = 枚举类名 + 枚举名
* value = 枚举
*/
private fun getEnumMap(ipConfigurationCls: Class<*>): Map<String, Any> {
val enumMap: MutableMap<String, Any> = HashMap()
val enumClasses = ipConfigurationCls.declaredClasses
for (enumClass in enumClasses) {
val enumConstants = enumClass.enumConstants ?: continue
for (enumConstant in enumConstants) {
// 枚举 Class 名 + 枚举名 = key
enumMap[enumClass.simpleName + "." + enumConstant.toString()] = enumConstant
}
}
return enumMap
}
Static IP 配置
步骤:
- 实例化 StaticIpConfiguration 对象 staticIpConfiguration
1.1. 设置 staticIpConfiguration.ipAddress = xxx
1.2. 设置 staticIpConfiguration.gateway = xxx
1.3. 设置 staticIpConfiguration.domains = xxx
1.4. 设置 staticIpConfiguration.dnsServers = xxx- 实例化 IpConfiguration() 对象 ipConfiguration
2.1. 设置 ipConfiguration.staticIpConfiguration = staticIpConfiguration
2.2. 设置 ipConfiguration.ipAssignment = xxx
2.3. 设置 ipConfiguration.proxySettings = xxx
2.4. 设置 ipConfiguration.httpProxy = xxx- 调用 ethernetManager.setConfiguration(ipConfiguration) 完成设置
/**
* 调用 EthernetManager.setConfiguration(IpConfiguration config) 设置静态 IP
*
* 步骤:
* - 实例化 StaticIpConfiguration 对象 staticIpConfiguration
* - 设置 staticIpConfiguration.ipAddress = xxx
* - 设置 staticIpConfiguration.gateway = xxx
* - 设置 staticIpConfiguration.domains = xxx
* - 设置 staticIpConfiguration.dnsServers = xxx
* - 实例化 IpConfiguration() 对象 ipConfiguration
* - 设置 ipConfiguration.staticIpConfiguration = staticIpConfiguration
* - 设置 ipConfiguration.ipAssignment = xxx
* - 设置 ipConfiguration.proxySettings = xxx
* - 设置 ipConfiguration.httpProxy = xxx
* - 调用 ethernetManager.setConfiguration(ipConfiguration) 完成设置
*/
@WorkerThread
fun setStaticIp(
ethernetManager: EthernetManager,
ip: String,
mask: String,
gateway: String,
dns: String
): Boolean {
try {
// 获取 StaticIpConfiguration 对象
val staticIpConfiguration = newStaticIpConfiguration(ip, mask, gateway, dns)
// 获取 IpConfiguration 对象
val ipConfiguration = newIpConfiguration(staticIpConfiguration)
// 通过 setConfiguration 方法设置静态 IP
val setConfigurationMethod = ethernetManager.javaClass.getDeclaredMethod(
"setConfiguration", ipConfiguration.javaClass
)
setConfigurationMethod.invoke(ethernetManager, ipConfiguration)
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
/**
* 获取 IpConfiguration 实例
*/
private fun newIpConfiguration(staticIpConfiguration: Any): Any {
// 获取 IpConfiguration 对象
val ipConfigurationCls = Class.forName("android.net.IpConfiguration")
val ipConfigurationEnum = getEnumMap(ipConfigurationCls)
val ipConfiguration = ipConfigurationCls.newInstance()
// 设置 ipConfiguration.staticIpConfiguration 为 staticIpConfiguration
val staticIpConfigurationField = ipConfigurationCls.getField("staticIpConfiguration")
staticIpConfigurationField[ipConfiguration] = staticIpConfiguration
// 设置 ipConfiguration.ipAssignment 为 IpAssignment.STATIC
val ipAssignment = ipConfigurationCls.getField("ipAssignment")
ipAssignment[ipConfiguration] = ipConfigurationEnum["IpAssignment.STATIC"]
// 设置 ipConfiguration.proxySettings 为 ProxySettings.NONE
val proxySettings = ipConfigurationCls.getField("proxySettings")
proxySettings[ipConfiguration] = ipConfigurationEnum["ProxySettings.NONE"]
// 设置 ipConfiguration.httpProxy 为 httpProxy
val httpProxy = ipConfigurationCls.getField("httpProxy")
httpProxy[ipConfiguration] = ProxyInfo.buildDirectProxy(null, 0)
return ipConfiguration
}
/**
* 获取 StaticIpConfiguration 实例
*/
private fun newStaticIpConfiguration(
ip: String,
mask: String,
gate: String,
dns: String
): Any {
// 获取 StaticIpConfiguration 对象
val staticIpConfigurationCls = Class.forName("android.net.StaticIpConfiguration")
val staticIpConfiguration = staticIpConfigurationCls.newInstance()
// 设置 ipAddress
val ipAddress = staticIpConfigurationCls.getField("ipAddress")
ipAddress[staticIpConfiguration] = newLinkAddress(ip, mask)
// 设置网关
val gateway = staticIpConfigurationCls.getField("gateway")
gateway[staticIpConfiguration] = InetAddress.getByName(gate)
// 设置子网掩码
val domains = staticIpConfigurationCls.getField("domains")
domains[staticIpConfiguration] = mask
// 设置 DNS
val dnsServers = staticIpConfigurationCls.getField("dnsServers")
val dnsList = dnsServers[staticIpConfiguration] as ArrayList<InetAddress>
dnsList.add(InetAddress.getByName(dns))
return staticIpConfiguration
}
/**
* 获取 LinkAddress 实例
*/
private fun newLinkAddress(ip: String, mask: String): Any? {
val linkAddressCls = Class.forName("android.net.LinkAddress")
val linkAddressConstructor = linkAddressCls.getDeclaredConstructor(
InetAddress::class.java,
Int::class.javaPrimitiveType
)
return linkAddressConstructor.newInstance(
InetAddress.getByName(ip),
getPrefixLength(mask)
)
}
/**
* 获取长度
*/
private fun getPrefixLength(mask: String): Int {
var count = 0
for (str in mask.split(".")) {
if (str == "255") {
++count
}
}
return count * 8
}
注意事项
以上代码需要是系统应用才能调用,需要在 AndroidManifest 文件中配置 android:sharedUserId=“android.uid.system”。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
android:sharedUserId="android.uid.system">
...
</manifest>