How to configure a static IP address, netmask, gateway programmatically on Android 3.x or 4.x How to configure a static IP address, netmask, gateway programmatically on Android 3.x or 4.x android android

How to configure a static IP address, netmask, gateway programmatically on Android 3.x or 4.x


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.

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 is IP address and its netmask as prefixLength (how many bit 1 in netmask).

mRoutes is ArrayList of RouteInfo that can indicate gateway.

mDnses is ArrayList of InetAddress for DNS.

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

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

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

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

Edit: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: The methods setIpAddress, setGateway, setDNS should be inputted as InetAddress type.


For Android 5.0+ a WIP solution. It does not yet work for some reason. Comments welcome.

void changeWifiConfiguration(boolean dhcp, String ip, int prefix, String dns1, String gateway) {    WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);    if(!wm.isWifiEnabled()) {        // wifi is disabled        return;    }    // get the current wifi configuration    WifiConfiguration wifiConf = null;    WifiInfo connectionInfo = wm.getConnectionInfo();    List<WifiConfiguration> configuredNetworks = wm.getConfiguredNetworks();       if(configuredNetworks != null) {        for (WifiConfiguration conf : configuredNetworks){            if (conf.networkId == connectionInfo.getNetworkId()){                wifiConf = conf;                break;                          }        }    }    if(wifiConf == null) {        // wifi is not connected        return;    }    try {        Class<?> ipAssignment = wifiConf.getClass().getMethod("getIpAssignment").invoke(wifiConf).getClass();        Object staticConf = wifiConf.getClass().getMethod("getStaticIpConfiguration").invoke(wifiConf);        if(dhcp) {            wifiConf.getClass().getMethod("setIpAssignment", ipAssignment).invoke(wifiConf, Enum.valueOf((Class<Enum>) ipAssignment, "DHCP"));            if(staticConf != null) {                staticConf.getClass().getMethod("clear").invoke(staticConf);            }        } else {            wifiConf.getClass().getMethod("setIpAssignment", ipAssignment).invoke(wifiConf, Enum.valueOf((Class<Enum>) ipAssignment, "STATIC"));            if(staticConf == null) {                Class<?> staticConfigClass = Class.forName("android.net.StaticIpConfiguration");                staticConf = staticConfigClass.newInstance();            }            // STATIC IP AND MASK PREFIX            Constructor<?> laConstructor = LinkAddress.class.getConstructor(InetAddress.class, int.class);            LinkAddress linkAddress = (LinkAddress) laConstructor.newInstance(                    InetAddress.getByName(ip),                     prefix);            staticConf.getClass().getField("ipAddress").set(staticConf, linkAddress);            // GATEWAY            staticConf.getClass().getField("gateway").set(staticConf, InetAddress.getByName(gateway));            // DNS            List<InetAddress> dnsServers = (List<InetAddress>) staticConf.getClass().getField("dnsServers").get(staticConf);            dnsServers.clear();            dnsServers.add(InetAddress.getByName(dns1));             dnsServers.add(InetAddress.getByName("8.8.8.8")); // Google DNS as DNS2 for safety            // apply the new static configuration            wifiConf.getClass().getMethod("setStaticIpConfiguration", staticConf.getClass()).invoke(wifiConf, staticConf);        }        // apply the configuration change        boolean result = wm.updateNetwork(wifiConf) != -1; //apply the setting        if(result) result = wm.saveConfiguration(); //Save it        if(result) wm.reassociate(); // reconnect with the new static IP    } catch(Exception e) {        e.printStackTrace();    }}


@Robin

Thanks your solution works fine for me on My Nexus device running on Android M 6.0.1.

I have replaced the // apply the configuration change boolean result = wm.updateNetwork(wifiConf) != -1; //apply the setting if(result) result = wm.saveConfiguration(); //Save it if(result) wm.reassociate(); // reconnect with the new static IP

with the following

int netId = manager.updateNetwork(wifiConf);boolean result =  netId!= -1; //apply the settingif(result){    boolean isDisconnected =  manager.disconnect();    boolean configSaved = manager.saveConfiguration(); //Save it    boolean isEnabled = manager.enableNetwork(wifiConf.networkId, true);    // reconnect with the new static IP    boolean isReconnected = manager.reconnect();                        }