Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
404 views
in Technique[技术] by (71.8m points)

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

How can a static IP address, netmask, gateway, DNS be programmatically configured on Android 5.x for Wi-Fi connection? Is there an open API (didn't find it) or hidden can be used for this? Could you also please give some examples if possible.

I know it's possible on Android 4.0+ but it doesn't work on Android 5.0

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...