Android 12 以太网开发,反射调用隐藏的api

package com.rxgb.settings.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.LinkAddress;
import android.util.Log;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 配置以太网的工具类
 */
@SuppressWarnings({"unused", "ConstantConditions", "JavaReflectionMemberAccess"})
public class EthernetUtils {
    private final String TAG = "EthernetUtils";
    private final Object ethManager;
    private final Method setConfigurationMethod;
    private final Method getConfigurationMethod;
    private final Method isAvailableMethod;
    private final Method getIpAddressMethod;
    private final Method getNetmaskMethod;
    private final Method getGatewayMethod;
    private final Method getDnsMethod;

    private final Method getAvailableInterfacesMethod;

    @SuppressLint({"WrongConstant", "SoonBlockedPrivateApi"})
    public EthernetUtils(Context context) {
        try {
            @SuppressLint("PrivateApi")
            Class<?> emClz = Class.forName("android.net.EthernetManager");
            ethManager = context.getSystemService("ethernet");
            @SuppressLint("PrivateApi")
            Class<?> ipCnClz = Class.forName("android.net.IpConfiguration");
            Object ipConfiguration = ipCnClz.newInstance();
            setConfigurationMethod = emClz.getDeclaredMethod("setConfiguration", String.class, ipConfiguration.getClass());
            getConfigurationMethod = emClz.getDeclaredMethod("getConfiguration", String.class);
            isAvailableMethod = emClz.getDeclaredMethod("isAvailable", String.class);
            getIpAddressMethod = emClz.getDeclaredMethod("getIpAddress", String.class);
            getNetmaskMethod = emClz.getDeclaredMethod("getNetmask", String.class);
            getGatewayMethod = emClz.getDeclaredMethod("getGateway", String.class);
            getDnsMethod = emClz.getDeclaredMethod("getDns", String.class);
            getAvailableInterfacesMethod = emClz.getDeclaredMethod("getAvailableInterfaces");
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException |
                 NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 是否是动态配置IP
     *
     * @param iface 网络接口
     * @return boolean 结果
     */
    public boolean isDynamic(String iface) {
        try {
            Object configuration = getConfigurationMethod.invoke(ethManager, iface);
            @SuppressLint("PrivateApi")
            Class<?> ipCnClz = Class.forName("android.net.IpConfiguration");
            Log.d(TAG, "isDynamic: " + ipCnClz.getField("ipAssignment").get(configuration));
            return ipCnClz.getField("ipAssignment").get(configuration).toString().equals("DHCP");
        } catch (IllegalAccessException | InvocationTargetException | ClassNotFoundException |
                 NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }

  

    /**
     * 设置动态ip
     *
     * @param iface 接口名称
     */
    public void setDynamicIp(String iface) {

        try {
            @SuppressLint("PrivateApi")
            Class<?> ipCnClz = Class.forName("android.net.IpConfiguration");
            Object ipConfiguration = ipCnClz.newInstance();
            Map<String, Object> ipConfigurationEnum = getIpConfigurationEnum(ipCnClz);
            Field ipAssignment = ipCnClz.getField("ipAssignment");
            ipAssignment.set(ipConfiguration, ipConfigurationEnum.get("IpAssignment.DHCP"));
            Field proxySettings = ipCnClz.getField("proxySettings");
            proxySettings.set(ipConfiguration, ipConfigurationEnum.get("ProxySettings.NONE"));
            setConfigurationMethod.invoke(ethManager, iface, ipConfiguration);
        } catch (IllegalAccessException | InstantiationException | NoSuchFieldException |
                 ClassNotFoundException | InvocationTargetException e) {
            Log.d(TAG, "setDynamicIp: " + e);
        }

    }

    /**
     * 设置静态ip
     *
     * @param iface     可用接口
     * @param ipAddress ip地址
     * @param netmask   子网掩码
     * @param gateway   网关
     * @param dns       dns
     */
    public void setStaticIp(String iface, String ipAddress, String netmask, String gateway, String dns) {
        if (!isAvailable(iface)) {
            return;
        }
        Object staticIpConfiguration = setStaticIpConfiguration(ipAddress, netmask, gateway, dns);
        try {
            Object ipConfiguration = newIpConfiguration(staticIpConfiguration);
            setConfigurationMethod.invoke(ethManager, iface, ipConfiguration);
        } catch (Exception e) {
//            throw new RuntimeException(e);
            Log.d(TAG, "setStaticIp: " + e);
        }
    }

    /**
     * 配置静态IP
     * @param staticIpConfiguration 静态IP配置
     */
    private Object newIpConfiguration(Object staticIpConfiguration) throws Exception {
        @SuppressLint("PrivateApi") Class<?> ipConfigurationCls = Class.forName("android.net.IpConfiguration");
        Object ipConfiguration = ipConfigurationCls.newInstance();
        Field staticIpConfigurationField = ipConfigurationCls.getField("staticIpConfiguration");
        staticIpConfigurationField.set(ipConfiguration, staticIpConfiguration);
        Map<String, Object> ipConfigurationEnum = getIpConfigurationEnum(ipConfigurationCls);
        Field ipAssignment = ipConfigurationCls.getField("ipAssignment");
        ipAssignment.set(ipConfiguration, ipConfigurationEnum.get("IpAssignment.STATIC"));
        Field proxySettings = ipConfigurationCls.getField("proxySettings");
        proxySettings.set(ipConfiguration, ipConfigurationEnum.get("ProxySettings.STATIC"));
        return ipConfiguration;
    }

    /**
     * 设置静态ip配置
     *
     * @param address ip地址
     * @param mask    子网掩码
     * @param gate    门关
     * @param dns     dns
     * @return {@link Object}
     */
    public Object setStaticIpConfiguration(String address, String mask, String gate, String dns) {
        try {
            Log.d(TAG, "setStaticIpConfiguration: address = " + address + " netmask = " + mask + " gateway = " + gate + " dns = " + dns);
            @SuppressLint("PrivateApi")
            Class<?> staticIpConfigurationClz = Class.forName("android.net.StaticIpConfiguration");
            Object staticIpConfiguration = staticIpConfigurationClz.newInstance();
            Field ipAddress = staticIpConfigurationClz.getField("ipAddress");
            Field netmask = staticIpConfigurationClz.getField("domains");
            Field gateway = staticIpConfigurationClz.getField("gateway");
            Field dnsServers = staticIpConfigurationClz.getField("dnsServers");
            ipAddress.set(staticIpConfiguration, getLinkAddress(InetAddress.getByName(address), getPrefixLength(mask)));
            netmask.set(staticIpConfiguration, mask);
            gateway.set(staticIpConfiguration, InetAddress.getByName(gate));
            ArrayList<InetAddress> dnsList = (ArrayList<InetAddress>) dnsServers.get(staticIpConfiguration);
            dnsList.add(InetAddress.getByName(dns));
            return staticIpConfiguration;
        } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException |
                 InstantiationException | UnknownHostException e) {
            Log.d(TAG, "setStaticIpConfiguration: " + e);
            return null;
        }
    }

    /**
     * 得到链接地址
     *
     * @param address 地址
     * @param length  长度
     * @return {@link LinkAddress}
     */
    public LinkAddress getLinkAddress(InetAddress address, int length) {
        try {
            Class<?> linkAddressClz = Class.forName("android.net.LinkAddress");
            Constructor<?> linkAddressCsr = linkAddressClz.getConstructor(InetAddress.class, int.class);
            return (LinkAddress) linkAddressCsr.newInstance(address, length);
        } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |
                 InstantiationException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取长度
     */
    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;
    }

    /**
     * 获得可用接口
     *
     * @return {@link String[]} 接口名称
     */
    public String[] getAvailableInterfaces() {
        try {
            return (String[]) getAvailableInterfacesMethod.invoke(ethManager);
        } catch (IllegalAccessException | InvocationTargetException e) {
            Log.d(TAG, "getAvailableInterfaces: " + e);
            return new String[]{};
        }
    }

    /**
     * 获取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;
    }

    /**
     * 是否可用
     *
     * @param iface iface
     * @return boolean
     */
    public boolean isAvailable(String iface) {
        try {
            return (boolean) isAvailableMethod.invoke(ethManager, iface);
        } catch (IllegalAccessException | InvocationTargetException e) {
            Log.d(TAG, "isAvailable: " + e);
            return false;
        }
    }

    /**
     * 获得ip地址
     *
     * @param iface iface
     * @return {@link String}
     */
    public String getIpAddress(String iface) {
        try {
            return (String) getIpAddressMethod.invoke(ethManager, iface);
        } catch (IllegalAccessException | InvocationTargetException e) {
            Log.d(TAG, "getIpAddress: " + e);
            return "0.0.0.0";
        }
    }

    /**
     * 得到子网掩码
     *
     * @param iface iface
     * @return {@link String}
     */
    public String getNetmask(String iface) {
        try {
            return (String) getNetmaskMethod.invoke(ethManager, iface);
        } catch (IllegalAccessException | InvocationTargetException e) {
            Log.d(TAG, "getNetmask: " + e);
            return "0.0.0.0";
        }
    }

    /**
     * 获得网关
     *
     * @param iface iface
     * @return {@link String}
     */
    public String getGateway(String iface) {
        try {
            return (String) getGatewayMethod.invoke(ethManager, iface);
        } catch (IllegalAccessException | InvocationTargetException e) {
            Log.d(TAG, "getGateway: " + e);
            return "0.0.0.0";
        }
    }

    /**
     * 获得dns
     *
     * @param iface iface
     * @return {@link String}
     */
    public String getDns(String iface) {
        try {
            return ((String) getDnsMethod.invoke(ethManager, iface)).replace(",", "");
        } catch (IllegalAccessException | InvocationTargetException e) {
            Log.d(TAG, "getDns: " + e);
            return "0.0.0.0";
        }
    }


    /**
     * ipv4正则表达式
     */
    private static final Pattern IPV4_REGEX =
            Pattern.compile(
                    "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

    /**
     * 判断是否为合法IPv4地址
     *
     * @param input 输入
     * @return boolean 判断结果
     */
    public static boolean isIPv4Address(final String input) {
        return IPV4_REGEX.matcher(input).matches();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44917215/article/details/130027132