android9下增加对eth0以太网IP地址的配置(以及如何修改并编译SDK)
增加对以太网IP地址的配置(app用反射方式获取EthernetManager和IEthernetManager的实例来用):
$ vi frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
在dump()函数前面添加函数:
public void updateIpConfiguration(String iface, IpConfiguration ipConfiguration){
Log.i(TAG, “Enter in updateIpConfiguration, iface == ” + iface);
mTracker.updateIpConfiguration(iface, ipConfiguration);
enforceAccessPermission();
start();
}
就是在这个dump上面增加上面函数:
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
$ vi frameworks/base/core/java/android/net/EthernetManager.java
在该行下增加:
private static final int MSG_AVAILABILITY_CHANGED = 1000;
新加的:
/**
* @hide
*/
public static final String ETHERNET_STATE_CHANGED_ACTION = “android.net.ethernet.ETHERNET_STATE_CHANGED”;
/**
* @hide
*/
public static final String EXTRA_ETHERNET_STATE = “ethernet_state”;
/**
* @hide
*/
public static final int ETHER_STATE_DISCONNECTED = 0;
/**
* @hide
*/
public static final int ETHER_STATE_CONNECTING = 1;
/**
* @hide
*/
public static final int ETHER_STATE_CONNECTED = 2;
/**
* @hide
*/
public static final int ETHER_STATE_DISCONNECTING = 3;
在EthernetManager类的尾部添加该类的函数:
public int getEthernetCarrierState(String ifname) {
/*
try {
return mService.getEthernetCarrierState(ifname);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return 0;
}
public String getEthernetMacAddress(String ifname) {
/*
try {
return mService.getEthernetMacAddress(ifname);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return “”;
}
public int getEthernetConnectState() {
/*
try {
return mService.getEthernetConnectState();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return 0;
}
public String getIpAddress() {
/*
try {
return mService.getIpAddress();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return “192.168.1.1”;
}
public String getNetmask() {
/*
try {
return mService.getNetmask();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return “255.255.255.0”;
}
public String getGateway() {
/*
try {
return mService.getGateway();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return “0.0.255.255”;
}
public String getDns() {
/*
try {
return mService.getDns();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return “0.0.0.0”;
}
public String dumpCurrentState(int state) {
/*
try {
return mService.dumpCurrentState(state);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
return “”;
}
public void disconnect(String iface) {
/*
try {
mService.disconnect(iface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
*/
}
public void updateIpConfiguration(String iface, IpConfiguration ipConfiguration){
try {
mService.updateIpConfiguration(iface, ipConfiguration);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
$ vi frameworks/base/core/java/android/net/IEthernetManager.aidl
在该行下增加一行:
void removeListener(in IEthernetServiceListener listener);
就是添加这个函数定义:
void updateIpConfiguration(String iface, in IpConfiguration ipConfiguration);
$ vi frameworks/base/core/java/android/net/EthernetManager.java
去掉这里的@hide
* @hide
*/
@SystemService(Context.ETHERNET_SERVICE)
public class EthernetManager {
$ vi frameworks/base/core/java/android/net/IpConfiguration.java
去掉这里的@hide
/**
* A class representing a configured network.
* @hide
*/
public class IpConfiguration implements Parcelable {
$ vi frameworks/base/core/java/android/net/StaticIpConfiguration.java
去掉这里的@hide
* @hide
*/
public class StaticIpConfiguration implements Parcelable {
$ vi frameworks/base/core/java/android/net/EthernetManager.java
去掉这里的@link
* the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
*/
public EthernetManager(Context context, IEthernetManager service) {
$ vi frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
在public void setConfiguration(String iface, IpConfiguration config) { 底部增加:
该行下面:
mTracker.updateIpConfiguration(iface, new IpConfiguration(config));
添加两行:
mTracker.removeInterface(iface);
mTracker.start();
}
$ vi frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
把
private void removeInterface(String iface) {
改成:
public void removeInterface(String iface) {
重新生成sdk库:
$ source build/envsetup.sh
$ lunch full_ac8257_demo-userdebug
$ make update-api
重新登录编译系统:
$ nohup ./allmake.sh -i &
重新生成sdk库:
$ ./allmake.sh sdklibs
生成位置: ac8257-androidP/sdklibs/
然后可以建立新的android studio 3.5的app
把生成的framework_classes.jar 放到 app/libs目录下。
然后源文件中可以导入以下类文件了:
import android.net.EthernetManager;
import android.net.IpConfiguration;
import android.net.LinkAddress;
修改AndroidManifest.xml,设置为系统用户来启动app(当然需要系统签名),并且赋予网络访问权限:
<manifest xmlns:android=”http://schemas.android.com/apk/res/android“
package=”com.maxshu.forethernetipset”
android:sharedUserId=”android.uid.system”>
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />
<uses-permission android:name=”android.permission.INTERNET” />
<uses-permission android:name=”android.permission.CHANGE_NETWORK_STATE” />
<uses-permission android:name=”android.permission.CONNECTIVITY_INTERNAL”/>
<uses-permission android:name=”android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS”/>
然后修改app目录下面的build.gradle,在android { 里面增加:
//为了避免 ask :app:mergeExtDexDebug FAILED 65535 错误。
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
然后需要优先使用framework_classes.jar里面的类,而不是android studio默认的sdk类,在app目录下面的build.gradle尾部增加(实际就是把app.iml文件的<orderEntry type=”jdk” jdkName=”Android API 29 Platform” jdkType=”Android SDK”/>这一行挪到其尾部):
preBuild {
doLast {
def imlFile = file(project.name + “.iml”)
println ‘Change ‘ + project.name + ‘.iml order’
try {
def parsedXml = (new XmlParser()).parse(imlFile)
def jdkNode = parsedXml.component[1].orderEntry.find { it.’@type’ == ‘jdk’ }
parsedXml.component[1].remove(jdkNode)
def sdkString = “Android API ” + android.compileSdkVersion.substring(“android-“.length()) + ” Platform”
new Node(parsedXml.component[1], ‘orderEntry’, [‘type’: ‘jdk’, ‘jdkName’: sdkString, ‘jdkType’: ‘Android SDK’])
groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
} catch (FileNotFoundException e) {
}
}
}
然后可以反射方式使用EthernetManager类和IEthernetManager类:
package com.maxshu.forethernetipset;
import android.content.Context;
import android.net.EthernetManager;
import android.net.IpConfiguration;
import android.net.LinkAddress;
import android.text.TextUtils;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
public class EthernetIP {
private static final String TAG = “EthernetUtils”;
/**
* @param context use Application context is better
* @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 = NetUtils.MaskStr2InetMask(netmask);
InetAddress inetAddr = null;
InetAddress gatewayAddr = InetAddress.getByName(gateway);
InetAddress dnsAddr = InetAddress.getByName(dns1);
if (TextUtils.isEmpty(ipAddress)) {
inetAddr = InetAddress.getByName(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();
}
if(!gateway.isEmpty()) {
mStaticIpConfiguration.gateway = gatewayAddr;
}
if(!dns1.isEmpty()) {
mStaticIpConfiguration.dnsServers.add(dnsAddr);
}
if (!dns2.isEmpty())
mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(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);
}
}
}
再加个辅助类NetUtils:
package com.maxshu.forethernetipset;
import android.content.Context;
import android.location.LocationManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.telephony.TelephonyManager;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
public class NetUtils {
// 网络是否可用
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return false;
} else {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}
// 得到当前网络类型
public static String getNetWorkType(Context context) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
int type = networkInfo.getType();
if (type == ConnectivityManager.TYPE_WIFI) {
return “wifi”;
} else if (type == ConnectivityManager.TYPE_MOBILE) {
return “mobile”;
}
return “unknow”;
}
//当前网络是不是wifi
public static boolean isConnectedByWifi(Context context) {
try {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = manager.getActiveNetworkInfo();
return (ni.getType() == ConnectivityManager.TYPE_WIFI ? true : false);
} catch (Exception e) {
}
return false;
}
// MOBILE网络是几G网2G?3G?4G?
// 返回几就是几G网
public static int getNetWorkClass(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
switch (telephonyManager.getNetworkType()) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
return 2;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
return 3;
case TelephonyManager.NETWORK_TYPE_LTE:
return 4;
default:
return 0;// unknow
}
}
// wifi网络是否可用
public static boolean isWifiConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (mWiFiNetworkInfo != null) {
return mWiFiNetworkInfo.isAvailable();
}
}
return false;
}
//mobile网络是否可用
public static boolean isMobileConnected(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mMobileNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (mMobileNetworkInfo != null) {
return mMobileNetworkInfo.isAvailable();
}
}
return false;
}
// 使用MOBILE网络时用来获取IP
public static String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = (NetworkInterface) en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = (InetAddress) enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress())
return inetAddress.getHostAddress().toString();
}
}
} catch (SocketException ex) {
}
return “0.0.0.0”;
}
// 使用Wifi时用来获取IP
public static String getWifiIpAddress(Context context) {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
return intToIp(ipAddress);
}
// 获取wifi的ssid(即wifi名称)
public static String getWifiSsid(Context context) {
String ssidApn = “”;
try {
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wi = wm.getConnectionInfo();
ssidApn = wi.getSSID();
} catch (Exception e) {
}
return ssidApn;
}
// 手机GPS是否开启
public static boolean isGpsEnable(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
// 返回运营商名字
public static String getNetworkOperatorName(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getNetworkOperatorName();
}
private static String intToIp(int i) {
return String.format(“%d.%d.%d.%d”, (i & 0xff), (i >> 8 & 0xff), (i >> 16 & 0xff), (i >> 24 & 0xff));
}
public static int MaskStr2InetMask(String maskStr){
StringBuffer sb ;
String str;
int inetmask = 0;
int count = 0;
String[] ipSegment = maskStr.split(“\\.”);
for(int n =0; n<ipSegment.length;n++){
sb = toBin(Integer.parseInt(ipSegment[n]));
str = sb.reverse().toString();
count=0;
for(int i=0; i<str.length();i++){
i=str.indexOf(“1”,i);
if(i==-1){
break;
}
count++;
}
inetmask+=count;
}
return inetmask;
}
private static StringBuffer toBin(int x)
{
StringBuffer result = new StringBuffer();
result.append(x % 2);
x /= 2;
while (x > 0)
{
result.append(x % 2);
x /= 2;
}
return result;
}
}