前言:因为项目需要设置安卓9.0系统的以太网静态ip地址,于是网上搜索相关资料。9.0系统以太网设置静态ip有关的,只有Github上有个MTK开发人员的分享,github链接:https://github.com/Dufre/Android-Settings-Ethernet,patch是在系统设置中加上以太网设置,用过后发现设置静态IP可以成功,但是无法连外网,解决方法是将 0001-Ethernet-Add-Static-IP-Settiings.patch 中的两个注释去掉,改成如下,且在设置的时候一定要配置正确的网关和DNS。
+ mStaticIpConfiguration.gateway=gatewayAddr;
+ mStaticIpConfiguration.dnsServers.add(dnsAddr);
打patch方式,比方说想打0001-Ethernet-Add-Static-IP-Settiings.patch,那么到/packages/apps/Settings目录,这个目录可以通过看patch文件中类似如下代码中a/b所在目录确认。
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4456aa0..ea33f8a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
// 进入到a所在目录即可。
然后执行patch -p1 < patch文件绝对路径,p后面是数字1,即可。
0001-Ethernet-IP-Add-Framework-Interface.patch这个patch到/frameworks/base目录导入。
0001-Ethernet-IP-Add-Framework-Function.patch这个patch到/frameworks/opt/net/ethernet目录导入。
接下来讲解如何通过一个方法来实现9.0以太网设置。
首先:在应用的清单文件中授权网络权限,主要应该是如下几个。同时
sharedUserId设置成"android.uid.system"。
其次:导入framework.jar,因为用到的类都是在framework中的。而且我测试的时候也使用了platform签名。
最后:终极方法如下,反射方式获取EthernetManager的实例参考 https://blog.csdn.net/aaa1050070637/article/details/79769788
private static final String TAG = "EthernetUtils";
/**
* @param context use Activity or Service context
* @param ipAddress ip address: like 192.168.1.168
* @param mode : STATIC or DHCP, set static or dhcp ip mode
* @param netmask ip mask, like 255.255.255.0
* @param gateway gateway, like 192.168.1.1
* @param dns1 dns 1
* @param dns2 dns 2, if mode=static, then can use "" or null
* eg. dhcp mode: setEthernetIP(ApplicationContext, "DHCP", "", "", "", "", "");
* static mode: setEthernetIP(ApplicationContext, "STATIC",
* "192.168.1.168", "255.255.255.0",
* "192.168.1.1", "114.114.114.114", "8.8.8.8");
* for android 9.0
* */
public static void setEthernetIP(Context context, String mode, String ipAddress, String netmask,
String gateway, String dns1, String dns2) {
if (context == null || (!"STATIC".equals(mode) && !"DHCP".equals(mode))) {
Log.d(TAG, " setEthernetIP failed, param incorrect context=" + context + ", mode=" + mode);
return;
}
try {
// get EthernetManager instance by reflect @{
Class ethernetManagerClass = Class
.forName("android.net.EthernetManager");
Class iEthernetManagerClass = Class
.forName("android.net.IEthernetManager");
// 获取ETHERNET_SERVICE参数
String ETHERNET_SERVICE = (String) Context.class.getField(
"ETHERNET_SERVICE").get(null);
// 获取ethernetManager服务对象
Object ethernetManager = context.getSystemService(ETHERNET_SERVICE);
// 获取在EthernetManager中的抽象类mService成员变量
Field mService = ethernetManagerClass.getDeclaredField("mService");
// 修改private权限
mService.setAccessible(true);
// 获取抽象类的实例化对象
Object mServiceObject = mService.get(ethernetManager);
Object ethernetManagerInstance = ethernetManagerClass
.getDeclaredConstructor(Context.class,
iEthernetManagerClass).newInstance(context,
mServiceObject);
EthernetManager mEthManager = (EthernetManager) ethernetManagerInstance;
// @}
String[] ifaces = mEthManager.getAvailableInterfaces();
if (ifaces.length <= 0) {
Log.e(TAG, " setEthernetIP failed ifaces.length <= 0");
return;
}
String mInterfaceName = ifaces[0];
Log.d(TAG, " setEthernetIP mInterfaceName=" + mInterfaceName);
if ("DHCP".equals(mode)) {
Log.i(TAG, " setEthernetIP set dhcp started");
IpConfiguration dhcpConfiguration = new IpConfiguration(IpConfiguration.IpAssignment.DHCP,
IpConfiguration.ProxySettings.NONE, null, null);
dhcpConfiguration.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
mEthManager.setConfiguration(mInterfaceName, dhcpConfiguration);
return;
}
if (TextUtils.isEmpty(ipAddress)
|| TextUtils.isEmpty(netmask) || TextUtils.isEmpty(gateway)
|| TextUtils.isEmpty(dns1)) {
Log.e(TAG, "setEthernetIP error has some param is null ipAddress=" + ipAddress
+ ", netmask=" + netmask + ", gateway=" + gateway
+ ", dns1=" + dns1 + ", dns2=" + dns2);
return;
}
StaticIpConfiguration mStaticIpConfiguration = new StaticIpConfiguration();
int prefixLength = maskStr2InetMask(netmask);
InetAddress inetAddr = null;
InetAddress gatewayAddr = getIPv4Address(gateway);
InetAddress dnsAddr = getIPv4Address(dns1);
if (TextUtils.isEmpty(ipAddress)) {
inetAddr = NetUtils.getLocalIPAddress();
} else {
String[] ipStr = ipAddress.split("\\.");
byte[] ipBuf = new byte[4];
for (int i = 0; i < 4; i++) {
ipBuf[i] = (byte) (Integer.parseInt(ipStr[i]) & 0xff);
}
try {
inetAddr = InetAddress.getByAddress(ipBuf);
Log.d(TAG, "setEthernetIP address correct inetAddr=" + inetAddr);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
if (inetAddr == null || inetAddr.getAddress().toString().isEmpty()
|| prefixLength == 0 || gatewayAddr.toString().isEmpty()
|| dnsAddr == null || dnsAddr.toString().isEmpty()) {
Log.d(TAG, " setEthernetIP address incorrect inetAddr=" + inetAddr);
return;
}
Class linkAddressClass = null;
linkAddressClass = Class.forName("android.net.LinkAddress");
Class[] cl = new Class[]{InetAddress.class, int.class};
Constructor cons = null;
//取得所有构造函数
try {
cons = linkAddressClass.getConstructor(cl);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//给传入参数赋初值
Object[] x = {inetAddr, prefixLength};
try {
mStaticIpConfiguration.ipAddress = (LinkAddress) cons.newInstance(x);
Log.d(TAG, " setEthernetIP mStaticIpConfiguration.ipAddress=" + mStaticIpConfiguration.ipAddress);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
mStaticIpConfiguration.gateway = gatewayAddr;
mStaticIpConfiguration.dnsServers.add(dnsAddr);
if (!dns2.isEmpty())
mStaticIpConfiguration.dnsServers.add(getIPv4Address(dns2));
Log.d(TAG, " setEthernetIP mStaticIpConfiguration ====" + mStaticIpConfiguration
+ ", inetAddr=" + inetAddr + ", mEthManager=" + mEthManager);
IpConfiguration ipConfiguration = new IpConfiguration(IpConfiguration.IpAssignment.STATIC,
IpConfiguration.ProxySettings.NONE, mStaticIpConfiguration, null);
ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.STATIC);
ipConfiguration.setStaticIpConfiguration(mStaticIpConfiguration);
mEthManager.setConfiguration(mInterfaceName, ipConfiguration);
} catch (Exception e) {
Log.e(TAG, "setEthernetIP error e=" + e.getMessage(), e);
}
}
注意事项: 该方法最好在Activity或者Fragment中执行,第一个参数使用活动、碎片或服务的context,否则容易报线程不对或初始化以太网管理器的错误,且执行完后需要重启系统才能生效。
android 9.0 GO系统 framework.jar 见资源:https://download.csdn.net/download/zzhceo/11548681
2019.12.12补充github工程地址:https://github.com/zzhceo/EthernetStaticIp,欢迎大家点赞收藏。