Set static IP and gateway programmatically in Android 6.x (Marshmallow)
Asked Answered
S

3

16

Can anybody tell me how can I set the static IP and gateway programmatically in Android 6?

I have read here and here.

Settings.System is not working anymore and goolgle says WIFI_STATIC_IP was deprecated in API level 17 and Use WifiManger instead. Unfortunately I cannot find anything about it in WifiManger and WifiConfigurationclasses.

Scram answered 20/10, 2016 at 13:17 Comment(2)
So why is this different from #10278961 ?Sewole
@Sewole the suggestions in referred examples does not work unless you set device owner.Sika
N
18

Since there's no official API I have to come up with a solution by modifying samples from the following code snipet and this answer. This solution works on devices from Lollipop upwards.

 @SuppressWarnings("unchecked")
 public 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});

        int netId = manager.updateNetwork(config);
        boolean result = netId != -1;
        if (result) {
            boolean isDisconnected = manager.disconnect();
            boolean configSaved = manager.saveConfiguration();
            boolean isEnabled = manager.enableNetwork(config.networkId, true);
            boolean isReconnected = manager.reconnect();
        }
    }

Helper functions,

    public static WifiConfiguration getCurrentWiFiConfiguration(Context context) {
            WifiConfiguration wifiConf = null;
            ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            if (networkInfo.isConnected()) {
                final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
                if (connectionInfo != null && !TextUtils.isEmpty(connectionInfo.getSSID())) {
                    List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
                    if (configuredNetworks != null) {
                        for (WifiConfiguration conf : configuredNetworks) {
                            if (conf.networkId == connectionInfo.getNetworkId()) {
                                wifiConf = conf;
                                break;
                            }
                        }
                    }
                }
            }
            return wifiConf;
        }

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

To use it,

WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiConfiguration wifiConf = WifiHelper.getCurrentWiFiConfiguration(getApplicationContext());

        try {
            setStaticIpConfiguration(wifiManager, wifiConf,
                    InetAddress.getByName("192.168.0.100"),
                    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();
        }

Finally you need to add those permissions in the manifest,

  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  <uses-permission android:name="android.permission.WRITE_SETTINGS" />
Notepaper answered 29/7, 2017 at 4:51 Comment(6)
Since I am not working with android API, can somebody check it out and tell me to put a tick on it?Scram
@Mogi what does that mean? you are not working with API ? what are you working with? just take this code add it to ur app and then try to use the app. you will know if it works or not !Dithyrambic
@Dithyrambic u understand it wrong :) I m not working with android anymore and question was asked in Oct 2016! I changed my JOB meanwhile. hahaScram
@Mogi omg i did not notice sorrry hahahah i was thinking what's wrong with this OP LOLDithyrambic
It works with WiFi, can you help how to make it work with Ethernet? On 5.1 of course.Uno
netId always returns -1 in Android 8+. Any other Proxysettings needed to fix thisEnscroll
S
2

I've dug some into the problem and my findings is that code that used to work for Andrdoi 5.x might work if the application is set to be the device owner.

Solution:

The solution is to add the device as deviceOwner. This will allow for static IP to be set using the 5.x hacks as referenced by Mogi. A good example of how this is done is using the example found here:

https://github.com/googlesamples/android-DeviceOwner/

Using adb shell and running the command:

dpm set-device-owner com.example.android.deviceowner/.DeviceOwnerReceiver

will make it ready to be allowed to do its job.

Sika answered 27/7, 2017 at 7:22 Comment(0)
B
0

I have successfully added and connected to open and PSK networks programmatically in my app (tried on devices running 5.1 as well as 6.0). However when I am trying this for enterprise network it does not work. I see that addNetwork() succeeds (returns positive net id) but when I look under Settings->Wi-Fi I don't see the SSID like I do for the other SSIDs I added. Anyone know why this would be? If I search the WiFiConfiguration list programmatically it does find the SSID. Here is the code I use:

wifiConf = new WifiConfiguration();
wifiConf.SSID = "\"dot1x-test\"";
wifiConf.BSSID = "c4:e9:84:43:48:e8";
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
    wifiConf.enterpriseConfig.setIdentity("name");
    wifiConf.enterpriseConfig.setPassword("testpassword");
    wifiConf.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
    wifiConf.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
}

netId = wifiMgr.addNetwork(wifiConf);
wifiMgr.disconnect();
wifiMgr.enableNetwork(netId, true);
wifiMgr.saveConfiguration();
wifiMgr.reconnect();
Boneblack answered 2/8, 2017 at 6:10 Comment(1)
This is not how StackOverflow works. If you got your own question, create one. Not make it as an answer to another question.Multure

© 2022 - 2024 — McMap. All rights reserved.