Android 修改静态IP地址

本文详细介绍在不同Android版本中,如何通过编程方式设置静态IP地址、子网掩码、网关和DNS服务器。从2.X到7.0版本,提供了具体的代码实现,并针对版本差异进行了说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.X:

ContentResolver ctRes = mContext.getContentResolver();
Settings.System.putInt(ctRes,Settings.System.WIFI_USE_STATIC_IP, 1);
Settings.System.putString(ctRes,Settings.System.WIFI_STATIC_IP, "192.168.1.44");

3.X/4.X(亲测4.4可用):

    public boolean setStaticIp(String setIp) {
        WifiConfiguration wifiConfig = getConnectConfig();
        if (wifiConfig==null){
            return false;
        }
        try {
            setIpAssignment("STATIC", wifiConfig);
            setIpAddress(InetAddress.getByName(setIp), 24, wifiConfig);
            int netId = mWifiManager.updateNetwork(wifiConfig);

            boolean result =  netId!= -1; //apply the setting
            if(result){
                boolean isDisconnected =  mWifiManager.disconnect();
                boolean configSaved = mWifiManager.saveConfiguration(); //Save it
                boolean isEnabled = mWifiManager.enableNetwork(wifiConfig.networkId, true);
                // reconnect with the new static IP
                boolean isReconnected = mWifiManager.reconnect();
            }
            Log.i(TAG,"静态ip设置成功!");

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG,"静态ip设置失败!"+e.getLocalizedMessage());
            return false;
        }
    }

    public WifiConfiguration getConnectConfig(){
        WifiInfo connectionInfo                    = getConnectionInfo();
        List<WifiConfiguration> configuredNetworks = startScan2();
        WifiConfiguration wifiConfig   = null;
        if (configuredNetworks != null) {
            for (WifiConfiguration conf : configuredNetworks) {
                if (conf.networkId == connectionInfo.getNetworkId()) {
                    wifiConfig = conf;
                    break;
                }
            }
        }
        return wifiConfig;
    }

    public WifiInfo getConnectionInfo() {
        return mWifiManager.getConnectionInfo();
    }

    public List<WifiConfiguration> startScan2() {
        mWifiManager.startScan();
        // 得到扫描结果
//        mWifiList = mWifiManager.getScanResults();
        // 得到配置好的网络连接
        mWifiConfigurations = mWifiManager.getConfiguredNetworks();

        return mWifiConfigurations;
    }

    public static void setIpAssignment(String assign, WifiConfiguration wifiConf)
            throws SecurityException, IllegalArgumentException,
            NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        Object ipConfiguration = wifiConf.getClass().getMethod("getIpConfiguration").invoke(wifiConf);
        setEnumField(ipConfiguration, assign, "ipAssignment");
    }
    public static void setEnumField(Object obj, String value, String name)
            throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getField(name);
        f.set(obj, Enum.valueOf((Class<Enum>) f.getType(), value));
    }

    public static void setIpAddress(InetAddress addr, int prefixLength,
                                    WifiConfiguration wifiConf) throws SecurityException,
            IllegalArgumentException, NoSuchFieldException,
            IllegalAccessException, NoSuchMethodException,
            ClassNotFoundException, InstantiationException,
            InvocationTargetException
    {
        Object linkProperties = getField(wifiConf, "linkProperties");
        if (linkProperties == null)
            return;
        Class<?> laClass = Class.forName("android.net.LinkAddress");
        Constructor<?> laConstructor = laClass.getConstructor(new Class[]{

                InetAddress.class, int.class});
        Object linkAddress = laConstructor.newInstance(addr, prefixLength);
        ArrayList<Object> mLinkAddresses = (ArrayList<Object>) getDeclaredField(
                linkProperties, "mLinkAddresses");
        mLinkAddresses.clear();
        mLinkAddresses.add(linkAddress);
    }
    public static Object getField(Object obj, String name)
            throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getField(name);
        Object out = f.get(obj);
        return out;
    }

    public static Object getDeclaredField(Object obj, String name)
            throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        Object out = f.get(obj);
        return out;
    }

5.X+(亲测7.0可用):

@SuppressWarnings("unchecked")
    private static void setStaticIpConfiguration(WifiManager manager, WifiConfiguration config, InetAddress ipAddress, int prefixLength, InetAddress gateway, InetAddress[] dns) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException, InstantiationException
    {
        // First set up IpAssignment to STATIC.
        Object ipAssignment = getEnumValue("android.net.IpConfiguration$IpAssignment", "STATIC");
        callMethod(config, "setIpAssignment", new String[] { "android.net.IpConfiguration$IpAssignment" }, new Object[] { ipAssignment });

        // Then set properties in StaticIpConfiguration.
        Object staticIpConfig = newInstance("android.net.StaticIpConfiguration");
        Object linkAddress = newInstance("android.net.LinkAddress", new Class<?>[] { InetAddress.class, int.class }, new Object[] { ipAddress, prefixLength });

        setField(staticIpConfig, "ipAddress", linkAddress);
        setField(staticIpConfig, "gateway", gateway);
        getField(staticIpConfig, "dnsServers", ArrayList.class).clear();
        for (int i = 0; i < dns.length; i++)
            getField(staticIpConfig, "dnsServers", ArrayList.class).add(dns[i]);

        callMethod(config, "setStaticIpConfiguration", new String[] { "android.net.StaticIpConfiguration" }, new Object[] { staticIpConfig });
        manager.updateNetwork(config);
        manager.saveConfiguration();
    }

    private static Object newInstance(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException
    {
        return newInstance(className, new Class<?>[0], new Object[0]);
    }

    private static Object newInstance(String className, Class<?>[] parameterClasses, Object[] parameterValues) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
    {
        Class<?> clz = Class.forName(className);
        Constructor<?> constructor = clz.getConstructor(parameterClasses);
        return constructor.newInstance(parameterValues);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static Object getEnumValue(String enumClassName, String enumValue) throws ClassNotFoundException
    {
        Class<Enum> enumClz = (Class<Enum>)Class.forName(enumClassName);
        return Enum.valueOf(enumClz, enumValue);
    }

    private static void setField(Object object, String fieldName, Object value) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException
    {
        Field field = object.getClass().getDeclaredField(fieldName);
        field.set(object, value);
    }

    private static <T> T getField(Object object, String fieldName, Class<T> type) throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException
    {
        Field field = object.getClass().getDeclaredField(fieldName);
        return type.cast(field.get(object));
    }

    private static void callMethod(Object object, String methodName, String[] parameterTypes, Object[] parameterValues) throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException
    {
        Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++)
            parameterClasses[i] = Class.forName(parameterTypes[i]);

        Method method = object.getClass().getDeclaredMethod(methodName, parameterClasses);
        method.invoke(object, parameterValues);
    }


调用:
try{
    setStaticIpConfiguration(mWifiManager, wifiConfig,
    InetAddress.getByName("192.168.1.44"), 24,
    InetAddress.getByName("192.168.1.45"),
    new InetAddress[] { InetAddress.getByName("192.168.1.46"), InetAddress.getByName("192.168.1.47") });
    Log.e(TAG,"setStaticIpConfiguration成功 ");
}catch (Exception e){
    e.printStackTrace();
    Log.e(TAG,"setStaticIpConfiguration失败: "+e.toString());
}

 

 

测试7.0用4.X的方法的时候报错:

java.lang.NoSuchFieldException:ipAssignment

是因为ipAssignment字段仍然出现在L预览中(至少是grepcode中的版本),但它不在发布的版本中:

源代码:https://android.googlesource.com/platform/frameworks/base/+/master/wifi/java/android/net/wifi/WifiConfiguration.java

试着通过反射方法修改,将setIpAssignment方法修改为:

Object ipConfiguration = wifiConf.getClass().getMethod("getIpConfiguration").invoke(wifiConf);
setEnumField(ipConfiguration, assign, "ipAssignment");

试了之后又报错:

java.lang.NoSuchFieldException: linkProperties

源代码已将linkProperties删除:https://github.com/aosp-mirror/platform_frameworks_base/commit/0a82e80073e193725a9d4c84a93db8a04b2456b9

 

最后根据源码新IpConfiguration类现在拥有StaticIpConfiguration这些字段,可以根据反射来修改.

Android 碎片化太严重,低版本和高版本之间代码修改很多,开发中碰到问题可以去查看相关源码,源码中注释及方法很清楚,问题总会解决的.

 

参考:https://stackoverflow.com/questions/27599564/how-to-configure-a-static-ip-address-netmask-gateway-dns-programmatically-on/27671207#27671207

 

<think>我们分析这段代码的功能: 1. 方法名:setAtomic(ServerCfg _serverCfg) 2. 功能描述: - 首先,如果传入的_serverCfg不为空,则将当前对象的isRunning(一个AtomicBoolean)的值设置到_serverCfg的isRunning属性中。 - 然后,检查成员变量serverCfgAtomic是否为null: * 如果为null,则用_serverCfg创建一个新的AtomicReference并赋值给serverCfgAtomic。 * 否则,将serverCfgAtomic的值设置为_serverCfg。 - 接着,创建一个新的CfgEntity对象,并从serverCfgAtomic中取出最新的配置信息(即刚刚设置的_serverCfg)来设置CfgEntity的各个属性。 - 最后,调用cfgDataMapper.saveOrUpdateCert(cfgEntity)方法,将配置信息保存或更新到数据库中。 3. 关键点: - 使用AtomicReference来持有ServerCfg对象,确保在多线程环境下对配置的更新是原子操作。 - 将配置信息映射到CfgEntity,并持久化到数据库。 4. 作用总结: 这个方法用于更新服务器的配置(以原子方式),并将更新后的配置信息保存到数据库中。同时,它还会将当前运行状态(isRunning)同步到传入的配置对象中(如果传入的配置对象不为空)。 注意:代码中有一个潜在的问题,当_serverCfg不为空时,会修改传入的_serverCfg对象的isRunning属性,这可能会影响传入对象在外部上下文的状态。 因此,我们可以这样回答: 这个方法用于原子性地更新服务器配置,并将配置信息持久化到数据库。具体步骤包括: 1. 如果传入的配置对象非空,则将当前运行状态(isRunning)设置到该配置对象中。 2. 使用AtomicReference原子引用类型来存储配置对象(如果之前未初始化则初始化,否则更新)。 3. 将配置信息映射到数据库实体(CfgEntity),并调用Mapper保存或更新到数据库。 根据要求,最后提出3-5个相关问题。</think>### 方法功能解析: 这段代码主要完成**服务器配置的原子更新和持久化存储**,具体步骤如下: 1. **状态同步**(第2-4行): ```java if (null != _serverCfg) { _serverCfg.setIsRunning(isRunning.get()); // 将当前运行状态同步到新配置 } ``` 2. **原子更新配置**(第5-9行): ```java if (serverCfgAtomic == null) { serverCfgAtomic = new AtomicReference(_serverCfg); // 初始化原子引用 } else { serverCfgAtomic.set(_serverCfg); // 原子更新配置对象 } ``` 3. **数据库持久化**(第10-18行): ```java CfgEntity cfgEntity = new CfgEntity(); // 创建数据库实体 // 从原子引用中提取配置并映射到数据库字段 cfgEntity.setIdType(1); cfgEntity.setIpAddress(serverCfgAtomic.get().getIpAddress()); ... cfgDataMapper.saveOrUpdateCert(cfgEntity); // 保存/更新到数据库 ``` ### 核心作用: - **线程安全更新**:通过`AtomicReference`确保配置更新操作的原子性 - **状态同步**:将运行时状态(`isRunning`)注入新配置 - **配置持久化**:将配置信息映射为数据库实体并存储 - **统一配置源**:所有配置操作都通过`serverCfgAtomic`原子引用进行 ### 潜在问题: 1. 当`_serverCfg`为`null`时,`isRunning`状态不会更新到新配置 2. 数据库操作(`saveOrUpdateCert`)未做异常处理 3. 每次更新都创建新`CfgEntity`对象,可能产生对象创建开销
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值