如何在Android 3.x或4.x上以编程方式配置静态IP地址,网络掩码,网关 [英] How to configure a static IP address, netmask, gateway programmatically on Android 3.x or 4.x

查看:120
本文介绍了如何在Android 3.x或4.x上以编程方式配置静态IP地址,网络掩码,网关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经检查了堆栈溢出问题 用于在Android应用程序中配置静态IP地址的API .

I have checked in Stack Overflow question API for configuring static IP addresses in an Android application.

它可以在Android 2.3之前运行.但是,在更高的API级别上没有运气.例如, 我把设置

It works until Android 2.3. However, there is no luck on a higher API level. For example, I put the setting

android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_USE_STATIC_IP, "1");        
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_IP, "192.168.0.100");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_NETMASK, "255.255.255.0");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_DNS1, "192.168.0.254");
android.provider.Settings.System.putString(getContentResolver(), android.provider.Settings.System.WIFI_STATIC_GATEWAY, "192.168.0.254");

但是我回过头来检查:

Setting --> Wi-Fi --> Long Press Access Point SSID --> Modify Network --> check Show advanced options

IP Settings字段仍表示为DHCP,而不是Static.

The IP Settings field is still stated DHCP but not Static.

我可以使用android.provider.Settings.System.getString()取回设置,这是事实.证明该设置保存在某个地方,但是系统只会忽略它.

It is true that I can use android.provider.Settings.System.getString() to get back what I set. It prove that the setting is saved somewhere but the system just ignore it.

系统使用Android 3.x和4.x上android.provider.Settings.System以外的设置,因为该设置是根据访问点SSID设置的.是否可以像在Android 2.3上一样修改一个SSID上的设置?

The system uses the setting other than android.provider.Settings.System on Android 3.x and 4.x as the setting is set per Access Point SSID. Can I modify the setting on one SSID just like how it works on Android 2.3?

推荐答案

我意识到在3.x或4.x上没有针对每个SSID的那些设置的API.因此,我检查了源代码,发现每个SSID的配置存储在从android.net.wifi.WifiManager获取的android.net.wifi.WifiConfiguration中.

I realise that there is no API on 3.x or 4.x for those setting per SSID. Therefore, I checked out the source code and found out that the configuration of each SSID is stored in android.net.wifi.WifiConfiguration which is gotten from android.net.wifi.WifiManager.

在下面的代码中,IpAssignment是一个枚举,可以是STAICDHCPNONE. linkProperties是对象存储的IP地址,网关,DNS等...

In the below code, IpAssignment is an Enum, either STAIC, DHCP or NONE. And linkProperties is the object store IP address, gateway, DNS, etc...

linkAddress是IP地址,其网络掩码为prefixLength(网络掩码中的多少位1).

linkAddress is IP address and its netmask as prefixLength (how many bit 1 in netmask).

mRoutesRouteInfoArrayList,可以指示网关.

mRoutes is ArrayList of RouteInfo that can indicate gateway.

mDnses是DNS的InetAddress中的ArrayList.

首先,使用WifiConfiguration SSID

Firstly, get the current configuration using WifiConfiguration SSID

WifiConfiguration wifiConf = null;
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiInfo connectionInfo = wifiManager.getConnectionInfo();
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();        
for (WifiConfiguration conf : configuredNetworks){
    if (conf.networkId == connectionInfo.getNetworkId()){
        wifiConf = conf;
        break;              
    }
}

由于隐藏了IpAssignmentlinkProperties,因此可以从反射中获取对象.

As the IpAssignment and linkProperties are hidden, the object can be gotten from reflection.

以下方法可以在SSID WifiConfiguration上设置声明的IP地址设置:

The following method can set the declared IP address setting on SSID WifiConfiguration:

    public static void setIpAssignment(String assign , WifiConfiguration wifiConf)
    throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException{
        setEnumField(wifiConf, assign, "ipAssignment");     
    }

    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 mLinkAddresses = (ArrayList)getDeclaredField(linkProperties, "mLinkAddresses");
        mLinkAddresses.clear();
        mLinkAddresses.add(linkAddress);        
    }

    public static void setGateway(InetAddress gateway, WifiConfiguration wifiConf)
    throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, 
    ClassNotFoundException, NoSuchMethodException, InstantiationException, InvocationTargetException{
        Object linkProperties = getField(wifiConf, "linkProperties");
        if(linkProperties == null)return;
        Class routeInfoClass = Class.forName("android.net.RouteInfo");
        Constructor routeInfoConstructor = routeInfoClass.getConstructor(new Class[]{InetAddress.class});
        Object routeInfo = routeInfoConstructor.newInstance(gateway);

        ArrayList mRoutes = (ArrayList)getDeclaredField(linkProperties, "mRoutes");
        mRoutes.clear();
        mRoutes.add(routeInfo);
    }

    public static void setDNS(InetAddress dns, WifiConfiguration wifiConf)
    throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException{
        Object linkProperties = getField(wifiConf, "linkProperties");
        if(linkProperties == null)return;

        ArrayList<InetAddress> mDnses = (ArrayList<InetAddress>)getDeclaredField(linkProperties, "mDnses");
        mDnses.clear(); //or add a new dns address , here I just want to replace DNS1
        mDnses.add(dns); 
    }

    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;
    }  

    private 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));
    }

在那之后,我可以为此SSID进行设置并更新WifiConfiguration.

After that, I can set setting and update WifiConfiguration for this SSID.

    try{
        setIpAssignment("STATIC", wifiConf); //or "DHCP" for dynamic setting
        setIpAddress(InetAddress.getByName("192.168.0.100"), 24, wifiConf);
        setGateway(InetAddress.getByName("4.4.4.4"), wifiConf);
        setDNS(InetAddress.getByName("4.4.4.4"), wifiConf);
        wifiManager.updateNetwork(wifiConf); //apply the setting
            wifiManager.saveConfiguration(); //Save it
    }catch(Exception e){
        e.printStackTrace();
    }

抱歉,我没有检查具有Android 4.x的silmilar UI的Android 3.x设备. 在Android 3.x中,网关存储在linkPropertiesmGateways中. mGateways是类型InetAddressArraylist.因此,以下操作应在Android 3.x中起作用.

Sorry for I don't check for Android 3.x device that have silmilar UI with Android 4.x. In Android 3.x, the gateway is storted in mGateways of linkProperties. mGateways is Arraylist of type InetAddress. Therefore, following should work in Android 3.x.

public static void setGateway(InetAddress gateway, WifiConfiguration wifiConf)
        throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, 
        ClassNotFoundException, NoSuchMethodException, InstantiationException, InvocationTargetException{
            Object linkProperties = getField(wifiConf, "linkProperties");
            if(linkProperties == null)return;
            ArrayList mGateways = (ArrayList)getDeclaredField(linkProperties, "mGateways");
            mGateways.clear();
            mGateways.add(gateway);
        }

Edit2:方法setIpAddresssetGatewaysetDNS应该作为InetAddress类型输入.

The methods setIpAddress, setGateway, setDNS should be inputted as InetAddress type.

这篇关于如何在Android 3.x或4.x上以编程方式配置静态IP地址,网络掩码,网关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆