How to configure a static IP address, netmask, gateway, DNS programmatically on Android 5.x (Lollipop) for Wi-Fi connection

There is still no open API, unfortunately.

The solution for Android 4.0 doesn’t work in LOLLIPOP because things have been moved around. In particular the new IpConfiguration class now holds the StaticIpConfiguration and all these fields. They can still be accessed by using reflection (with all the brittleness that entails) with something like this.

Warning, this code is Android 5.0-only. You’ll need to check Build.VERSION.SDK_INT and act accordingly.

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

With the following helper methods to handle reflection:

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

For example, you can call it like this:

public void test(Context context)
{
    WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration wifiConf = ... /* Get Wifi configuration you want to update */

    if (wifiConf != null)
    {
        try
        {
            setStaticIpConfiguration(manager, wifiConf,
                InetAddress.getByName("10.0.0.1"), 24,
                InetAddress.getByName("10.0.0.2"),
                new InetAddress[] { InetAddress.getByName("10.0.0.3"), InetAddress.getByName("10.0.0.4") });
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

As a reference, you might want to take a look at the WifiConfigController class in the framework (though it uses these classes directly instead of via reflection).

Leave a Comment