Android 系统有线网络静态属性配置
本篇主要涉及Android 7【SDK 25】以上系统应用,设置有线网络的静态IP、子网掩码、网关等属性设置;
有线网络提供了管理类EthernetManager
,获取开关状态、获取有线网络信息、设置动态IP
静态IP
子网掩码
网关Ip
获取都通过它,在标准的Android
接口中,EthernetManager
是隐藏的,所以在Framework
没有放开的情况下,只能通过Java反射的形式进行调用,下面就先了解相关的API
和方法。
注意:反射EthernetManager的前提是你的应用是系统级应用,否则反射的时候会报缺少权限,即使在AndroidManifest.xml清单里面配了也无济于事
1、介绍framework层网络配置相关类
typescript
package android.net;
@SystemService(Context.CONNECTIVITY_SERVICE)
public class ConnectivityManager {
/**
* Create a new EthernetManager instance.
* Applications will almost always want to use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
*/
public EthernetManager(Context context, IEthernetManager service) {
mContext = context;
mService = service;
}
/*
* 阅读framework源码,我们发现ConnectivityManager的构造函数,需要两个参数
* 最重要一个是IEthernetManager,是一个系统服务,那么说明在Android SDK里面,肯定会有个service Tag可以直接可以获得EthernetManager
*/
/**
* Get Ethernet configuration.
* @return the Ethernet Configuration, contained in {@link IpConfiguration}.
*/
public IpConfiguration getConfiguration(String iface) {
try {
return mService.getConfiguration(iface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/*
* getConfiguration 获取iface网卡的配置
*/
/**
* Set Ethernet configuration.
*/
public void setConfiguration(String iface, IpConfiguration config) {
try {
mService.setConfiguration(iface, config);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/*
* setConfiguration 设置iface网卡的配置
* IpConfiguration 一个网卡配置信息的类,也是android.net这个包下面的
*/
}
首先先介绍一下android.net.IpConfiguration
这个类的所有字段的含义
java
package android.net;
/**
* A class representing a configured network.
* @hide
*/
public class IpConfiguration implements Parcelable {
public IpAssignment ipAssignment;
public StaticIpConfiguration staticIpConfiguration;
public ProxySettings proxySettings;
public ProxyInfo httpProxy;
/*
ipAssignment:表示 IP 地址分配的方式,可能的取值包括:
IpAssignment.DHCP:通过 DHCP 自动分配 IP 地址。
IpAssignment.STATIC:使用静态 IP 地址配置。
IpAssignment.UNASSIGNED:未分配IP,可作为无效值。
proxySettings:表示代理服务器设置,可能的取值包括:
ProxySettings.NONE:不使用代理。
ProxySettings.STATIC:使用静态代理设置。
ProxySettings.PAC:根据 PAC (Proxy Auto-Config) 文件配置代理。
ProxySettings.UNASSIGNED:未分配代理设置。
*/
}
当 IpAssignment
设置为静态时STATIC
,则需要使用 StaticIpConfiguration 来进行设定 静态IP、掩码、网关和DNS;StaticIpConfiguration
也是 android.net这个包下面的类
下面继续看 StaticIpConfiguration这个类的一些字段的含义
java
package android.net;
import android.net.LinkAddress;
import java.net.InetAddress;
/**
* Class that describes static IP configuration.
*
* This class is different from LinkProperties because it represents
* configuration intent. The general contract is that if we can represent
* a configuration here, then we should be able to configure it on a network.
* The intent is that it closely match the UI we have for configuring networks.
*
* In contrast, LinkProperties represents current state. It is much more
* expressive. For example, it supports multiple IP addresses, multiple routes,
* stacked interfaces, and so on. Because LinkProperties is so expressive,
* using it to represent configuration intent as well as current state causes
* problems. For example, we could unknowingly save a configuration that we are
* not in fact capable of applying, or we could save a configuration that the
* UI cannot display, which has the potential for malicious code to hide
* hostile or unexpected configuration from the user: see, for example,
* http://b/12663469 and http://b/16893413 .
*
* @hide
*/
public class StaticIpConfiguration implements Parcelable {
public LinkAddress ipAddress;
public InetAddress gateway;
public final ArrayList<InetAddress> dnsServers;
public String domains;
/*
ipAddress:表示静态 IP 地址。
gateway:表示静态 IP 的默认网关。
dnsServers:表示静态 IP 配置的 DNS 服务器的 IP 地址列表。
domains:表示与静态 IP 配置相关的 DNS 搜索域。
*/
}
2、使用反射调用系统方法设置网络属性
直接上完整调用的代码;
ini
/**
* 设置静态ip、子网掩码、网关
* @param iFace 网卡名称,如:eth0
* @param isDhcpMode 是否是DHCP模式
* @param ip ip 地址 //当前不支持ipv6
* @param mask 掩码
* @param gateway 网关
*/
public static void setStaticIpConfiguration(String iFace,boolean isDhcpMode,String ip,String mask,String gateway){
try {
//1| 获得EthernetManager
Object objEthernetManager = AppGlobal.getApplicationContext().getSystemService("ethernet");
//2| 构造 IpConfiguration的成员 IpAssignment ProxySettings StaticIpConfiguration ProxyInfo
Class<?> aClass = ReflectHelper.getClass("android.net.NetworkUtils");
Method numericToInetAddress = aClass.getDeclaredMethod("numericToInetAddress", String.class);
numericToInetAddress.setAccessible(true);
Class<?> classStaticIpConfiguration = ReflectHelper.getClass("android.net.StaticIpConfiguration");
Object objStaticIpConfiguration = null;
if (!isDhcpMode){
InetAddress ipV4InetAddress = (InetAddress) numericToInetAddress.invoke(null, ip);
InetAddress gatewayInetAddress = (InetAddress) numericToInetAddress.invoke(null, gateway);
objStaticIpConfiguration = classStaticIpConfiguration.newInstance();
ReflectHelper.setField(objStaticIpConfiguration, "ipAddress", createLinkAddress(ipV4InetAddress, CommonUtils.getNetmaskLength(mask)));
ReflectHelper.setField(objStaticIpConfiguration, "gateway", gatewayInetAddress);
OsduiLog.mtuiHintLog(TAG, "setStaticIpConfiguration objStaticIpConfiguration: " + objStaticIpConfiguration);
}
Class<?> classIpConfiguration = ReflectHelper.getClass("android.net.IpConfiguration");
Class<?> classProxyInfo = ReflectHelper.getClass("android.net.ProxyInfo");
Class<?> ipAssignment = ReflectHelper.getClass("android.net.IpConfiguration$IpAssignment");
Class<?> proxySettings = ReflectHelper.getClass("android.net.IpConfiguration$ProxySettings");
Object objIpAssignment = ReflectHelper.getField(ipAssignment, null, isDhcpMode? "DHCP":"STATIC");//设置DHCP模式
Object objProxySettings = ReflectHelper.getField(proxySettings, null, "NONE");
//3| 构造出 IpConfiguration
Constructor<?> declaredConstructor = classIpConfiguration.getDeclaredConstructor(ipAssignment, proxySettings, classStaticIpConfiguration, classProxyInfo);
Object objIpConfiguration = declaredConstructor.newInstance(objIpAssignment, objProxySettings, objStaticIpConfiguration, null);
OsduiLog.mtuiHintLog(TAG, "setStaticIpConfiguration objIpConfiguration: " + objIpConfiguration);
//4| 调用 EthernetManager里的setConfiguration方法
ReflectHelper.invokeMethod(objEthernetManager,"setConfiguration",
new Class[]{String.class,classIpConfiguration},new Object[]{iFace,objIpConfiguration});
} catch (Exception e) {
e.printStackTrace();
}
}
这里还涉及了一个 android.net.NetworkUtils
,这个系统层直接提供的网络工具类,主要用于一个Int的ip转换成java.net.InetAddress 对象;如果不想用也可以自己构造出来;
这里还涉及了一个InetAddress转成LinkAddress方法,这里一并转换出来
ini
private static LinkAddress createLinkAddress(InetAddress ipAddress, int prefixLength) {
try {
Class<?> clazz = Class.forName("android.net.LinkAddress");
Class<?>[] parTypes = new Class<?>[2];
parTypes[0] = InetAddress.class;
parTypes[1] = int.class;
Constructor<?> constructor = clazz.getConstructor(parTypes);
Object[] pars = new Object[2];
pars[0] = ipAddress;
pars[1] = prefixLength;
return (LinkAddress) constructor.newInstance(pars);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
有线网络是通过EthernetManager
来设置静态网络属性,而无线网络则不需要这么复杂,但也需要用到StaticIpConfiguration
,但本次不进行展开;如有需要请点赞收藏关注支持,后续会继续更新跟网络相关的内容,Android开发;
Ps:点赞关注越多,更新越快;如遇特别难题,可私信或者评论,会及时回复~不过需要您的点赞收藏
至此,以太网络的相关操作介绍完毕。