Android设置以太网(LAN)静态IP
背景
-
需:因公司设备需要在一些特殊环境地方运行,使用不了物联网卡以及wifi,故而只能用网线来联网,也就是需要以太网。
-
查:通过资料,一般实现有2种方式,一种是通过反射获取EthernetManager方法进行设置,或者通过导入系统class.jar文件来直接调用EthernetManager方法。因要支持不同系统且多主板类型不与其他原有主板厂商的api冲突,就只要使用反射的方式来进行设置了。(其实android5.0系统上在设置里有Ethernet的相关配置,可惜我这最起码都是android6.0起步,而且我也说(打)不过运维大哥。)
技术实现
-
判断当前是否网线联网-LAN模式
NetworkInfo lanInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET); if (null != lanInfo) { NetworkInfo.State state = lanInfo.getState(); if (null != state) { if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) { return true; } } } -
利用反射进行DHCP或静态ip设置
- 默认是DHCP进行获取--也有的网管会关闭DHCP,那么返回的只能是0.0.0.0了。
/**
* 设置以太网动态获取IP
*/
public static boolean setDynamicIp(Context context) {
try {
@SuppressLint("PrivateApi") Class<?> ethernetManagerCls = Class.forName("android.net.EthernetManager");
//获取EthernetManager实例
@SuppressLint("WrongConstant") Object ethManager = context.getSystemService("ethernet");
//创建IpConfiguration
@SuppressLint("PrivateApi") Class<?> ipConfigurationCls = Class.forName("android.net.IpConfiguration");
Object ipConfiguration = ipConfigurationCls.newInstance();
//获取ipAssignment、proxySettings的枚举值
Map<String, Object> ipConfigurationEnum = getIpConfigurationEnum(ipConfigurationCls);
//设置ipAssignment
Field ipAssignment = ipConfigurationCls.getField("ipAssignment");
ipAssignment.set(ipConfiguration, ipConfigurationEnum.get("IpAssignment.DHCP"));
//设置proxySettings
Field proxySettings = ipConfigurationCls.getField("proxySettings");
proxySettings.set(ipConfiguration, ipConfigurationEnum.get("ProxySettings.NONE"));
//获取EthernetManager的setConfiguration()
Method setConfigurationMethod = ethernetManagerCls.getDeclaredMethod("setConfiguration", ipConfiguration.getClass());
//设置动态IP
setConfigurationMethod.invoke(ethManager, ipConfiguration);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
- 静态配置IP--注意要先插好网线呀。实际操作中,就有大佬忘记插网线,反复提bug给俺。
/**
* 设置以太网静态IP地址
*
* @param address ip地址
* @param mask 子网掩码
* @param gate 网关
* @param dns dns
*/
public static boolean setEthernetStaticIp(Context context, String address, String mask, String gate, String dns) {
try {
@SuppressLint("PrivateApi") Class<?> ethernetManagerCls = Class.forName("android.net.EthernetManager");
//获取EthernetManager实例
@SuppressLint("WrongConstant") Object ethManager = context.getSystemService("ethernet");
//创建StaticIpConfiguration
Object staticIpConfiguration = newStaticIpConfiguration(address, gate, mask, dns);
//创建IpConfiguration
Object ipConfiguration = newIpConfiguration(staticIpConfiguration);
//获取EthernetManager的setConfiguration()
Method setConfigurationMethod = ethernetManagerCls.getDeclaredMethod("setConfiguration", ipConfiguration.getClass());
//保存静态ip设置
saveIpSettings(context, address, mask, gate, dns);
//设置静态IP
setConfigurationMethod.invoke(ethManager, ipConfiguration);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 获取StaticIpConfiguration实例
*/
private static Object newStaticIpConfiguration(String address, String gate, String mask, String dns) throws Exception {
@SuppressLint("PrivateApi") Class<?> staticIpConfigurationCls = Class.forName("android.net.StaticIpConfiguration");
//实例化StaticIpConfiguration
Object staticIpConfiguration = staticIpConfigurationCls.newInstance();
Field ipAddress = staticIpConfigurationCls.getField("ipAddress");
Field gateway = staticIpConfigurationCls.getField("gateway");
Field domains = staticIpConfigurationCls.getField("domains");
Field dnsServers = staticIpConfigurationCls.getField("dnsServers");
//设置ipAddress
ipAddress.set(staticIpConfiguration, newLinkAddress(address, mask));
//设置网关
gateway.set(staticIpConfiguration, InetAddress.getByName(gate));
//设置掩码
domains.set(staticIpConfiguration, mask);
//设置dns
ArrayList<InetAddress> dnsList = (ArrayList<InetAddress>) dnsServers.get(staticIpConfiguration);
dnsList.add(InetAddress.getByName(dns));
return staticIpConfiguration;
}
/**
* 获取LinkAddress实例
*/
private static Object newLinkAddress(String address, String mask) throws Exception {
Class<?> linkAddressCls = Class.forName("android.net.LinkAddress");
Constructor<?> linkAddressConstructor = linkAddressCls.getDeclaredConstructor(InetAddress.class, int.class);
return linkAddressConstructor.newInstance(InetAddress.getByName(address), getPrefixLength(mask));
}
/**
* 获取IpConfiguration实例
*/
private static Object newIpConfiguration(Object staticIpConfiguration) throws Exception {
@SuppressLint("PrivateApi") Class<?> ipConfigurationCls = Class.forName("android.net.IpConfiguration");
Object ipConfiguration = ipConfigurationCls.newInstance();
//设置StaticIpConfiguration
Field staticIpConfigurationField = ipConfigurationCls.getField("staticIpConfiguration");
staticIpConfigurationField.set(ipConfiguration, staticIpConfiguration);
//获取ipAssignment、proxySettings的枚举值
Map<String, Object> ipConfigurationEnum = getIpConfigurationEnum(ipConfigurationCls);
//设置ipAssignment
Field ipAssignment = ipConfigurationCls.getField("ipAssignment");
ipAssignment.set(ipConfiguration, ipConfigurationEnum.get("IpAssignment.STATIC"));
//设置proxySettings
Field proxySettings = ipConfigurationCls.getField("proxySettings");
proxySettings.set(ipConfiguration, ipConfigurationEnum.get("ProxySettings.STATIC"));
return ipConfiguration;
}
/**
* 获取IpConfiguration的枚举值
*/
private static Map<String, Object> getIpConfigurationEnum(Class<?> ipConfigurationCls) {
Map<String, Object> enumMap = new HashMap<>();
Class<?>[] enumClass = ipConfigurationCls.getDeclaredClasses();
for (Class<?> enumC : enumClass) {
Object[] enumConstants = enumC.getEnumConstants();
if (enumConstants == null) continue;
for (Object enu : enumConstants) {
enumMap.put(enumC.getSimpleName() + "." + enu.toString(), enu);
}
}
return enumMap;
}
/**
* 保存静态ip设置
*/
private static void saveIpSettings(Context context, String address, String mask, String gate, String dns) {
ContentResolver contentResolver = context.getContentResolver();
Settings.Global.putString(contentResolver, "ethernet_static_ip", address);
Settings.Global.putString(contentResolver, "ethernet_static_mask", mask);
Settings.Global.putString(contentResolver, "ethernet_static_gateway", gate);
Settings.Global.putString(contentResolver, "ethernet_static_dns1", dns);
}
/**
* 获取长度
*/
private static int getPrefixLength(String mask) {
String[] strs = mask.split("\.");
int count = 0;
for (String str : strs) {
if (str.equals("255")) {
++count;
}
}
return count * 8;
}
就这样我们就可以配置相关静态IP了,完结撒花~!
/**
* 获取IP地址
*/
public static String getIpAddress() {
String interfaceName = "eth0";
try {
//获取本机所有的网络接口
Enumeration<NetworkInterface> enNetworkInterface = NetworkInterface.getNetworkInterfaces();
//判断 Enumeration 对象中是否还有数据
while (enNetworkInterface.hasMoreElements()) {
//获取 Enumeration 对象中的下一个数据
NetworkInterface networkInterface = enNetworkInterface.nextElement();
// 判断网口是否在使用
if (!networkInterface.isUp()) {
continue;
}
// 网口名称是否和需要的相同
if (!interfaceName.equals(networkInterface.getDisplayName())) {
continue;
}
//getInetAddresses 方法返回绑定到该网卡的所有的 IP 地址
Enumeration<InetAddress> enInetAddress = networkInterface.getInetAddresses();
while (enInetAddress.hasMoreElements()) {
InetAddress inetAddress = enInetAddress.nextElement();
if (inetAddress instanceof Inet4Address) {
//判断是否未ipv4
return inetAddress.getHostAddress();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "0.0.0.0";
}
/**
* 获取网关
*/
public static String getGateWay() {
String[] arr;
try {
Process process = Runtime.getRuntime().exec("ip route list table 0");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String string = in.readLine();
arr = string.split("\s+");
return arr[2];
} catch (IOException e) {
e.printStackTrace();
}
return "0.0.0.0";
}
/**
* 获取子网掩码
*/
public static String getNetMask() {
String interfaceName = "eth0";
try {
//获取本机所有的网络接口
Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
//判断 Enumeration 对象中是否还有数据
while (networkInterfaceEnumeration.hasMoreElements()) {
//获取 Enumeration 对象中的下一个数据
NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
if (networkInterface.isUp() && interfaceName.equals(networkInterface.getDisplayName())) {
//判断网口是否在使用,判断是否时我们获取的网口
for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
if (interfaceAddress.getAddress() instanceof Inet4Address) {
//仅仅处理ipv4
switch (interfaceAddress.getNetworkPrefixLength()) {
case 8:
return "255.0.0.0";
case 16:
return "255.255.0.0";
case 24:
return "255.255.255.0";
}
}
}
break;
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return "0.0.0.0";
}
/**
* 获取dns(仅获取IPV4的DNS)
*/
public static String getDns(Context context) {
try {
String[] dnsServers = getDnsFromCmd();
if (dnsServers.length == 0) {
dnsServers = getDnsFromConnectionManager(context);
}
StringBuilder sb = new StringBuilder();
for (String dnsServer : dnsServers) {
sb.append(dnsServer);
sb.append(",");
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return "0.0.0.0";
}
//通过 getprop 命令获取
private static String[] getDnsFromCmd() {
LinkedList<String> dnsServers = new LinkedList<>();
try {
Process process = Runtime.getRuntime().exec("getprop");
InputStream inputStream = process.getInputStream();
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(inputStream));
String line;
while ((line = lnr.readLine()) != null) {
int split = line.indexOf("]: [");
if (split == -1) continue;
String property = line.substring(1, split);
String value = line.substring(split + 4, line.length() - 1);
if (property.endsWith(".dns")
|| property.endsWith(".dns1")
|| property.endsWith(".dns2")
|| property.endsWith(".dns3")
|| property.endsWith(".dns4")) {
InetAddress ip = InetAddress.getByName(value);
if (ip instanceof Inet4Address) {
value = ip.getHostAddress();
if (value == null) {
continue;
}
if (value.length() == 0) {
continue;
}
dnsServers.add(value);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return dnsServers.isEmpty() ? new String[0] : dnsServers.toArray(new String[0]);
}
private static String[] getDnsFromConnectionManager(Context context) {
LinkedList<String> dnsServers = new LinkedList<>();
if (context != null) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
for (Network network : connectivityManager.getAllNetworks()) {
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if (networkInfo != null && networkInfo.getType() == activeNetworkInfo.getType()) {
LinkProperties lp = connectivityManager.getLinkProperties(network);
for (InetAddress addr : lp.getDnsServers()) {
if (addr instanceof Inet4Address) {
dnsServers.add(addr.getHostAddress());
}
}
}
}
}
}
}
return dnsServers.isEmpty() ? new String[0] : dnsServers.toArray(new String[0]);
}
好了,可以给运维大哥交差了。