11

How can I set ProxySettings and ProxyProperties on an Android Wi-Fi connection using Java (programatically)?

As ipAssignment, linkProperties, ProxySettings and ProxyProperties are hidden fields within WifiConfiguration on Android 3.1 and up, I need to be able to enum the class and use the fields.

Following the code sample using the link below, I can set a static IP address, gateway and DNS for a particular Wi-Fi connection, but I also need to set Wificonfiguration.ProxySettings.STATIC and ProxyProperties

See Stack Overflow question How to configue a static IP address, netmask, gateway programmatically on Android 3.x or 4.x.

For example,

WifiConfiguration config = new WifiConfiguration(configuration);
config.ipAssignment = WifiConfiguration.IpAssignment.UNASSIGNED;
config.proxySettings = WifiConfiguration.ProxySettings.STATIC;
config.linkProperties.setHttpProxy(new ProxyProperties("127.0.0.1", 3128, ""));

Looking for something like:

setProxySettings("STATIC", wifiConf);
setProxyProperties("proxyserver.mine.com.au", 8080, ""); // Set Proxy server and port.
wifiManager.updateNetwork(wifiConf); //apply the setting

Using the following code from coolypf .ipAssignment .ProxySettings and linkProperties are hidden...

    WifiManager manager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
manager.asyncConnect(this, new Handler());
if (!manager.isWifiEnabled()) return;
    List<WifiConfiguration> configurationList = manager.getConfiguredNetworks();
    WifiConfiguration configuration = null;
    int cur = manager.getConnectionInfo().getNetworkId();
    for (int i = 0; i < configurationList.size(); ++i)
    {
        WifiConfiguration wifiConfiguration = configurationList.get(i);
        if (wifiConfiguration.networkId == cur)
        configuration = wifiConfiguration;
    }
    if (configuration == null) return;
    WifiConfiguration config = new WifiConfiguration(configuration);
    config.ipAssignment = WifiConfiguration.IpAssignment.UNASSIGNED;
    config.proxySettings = WifiConfiguration.ProxySettings.STATIC;

    config.linkProperties.clear();

    config.linkProperties.setHttpProxy(new ProxyProperties("127.0.0.1", 3128, ""));

    manager.saveNetwork(config);
Community
  • 1
  • 1
ShaneOss
  • 172
  • 1
  • 2
  • 9

3 Answers3

15

Here's some code that should allow you to set/unset ProxyProperties. It uses some of the same code from the link above. The settings do not seem to take effect with the disconnect/reconnect.

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

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

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


WifiConfiguration GetCurrentWifiConfiguration(WifiManager manager)
{
    if (!manager.isWifiEnabled()) 
        return null;

    List<WifiConfiguration> configurationList = manager.getConfiguredNetworks();
    WifiConfiguration configuration = null;
    int cur = manager.getConnectionInfo().getNetworkId();
    for (int i = 0; i < configurationList.size(); ++i)
    {
        WifiConfiguration wifiConfiguration = configurationList.get(i);
        if (wifiConfiguration.networkId == cur)
            configuration = wifiConfiguration;
    }

    return configuration;
}

void setWifiProxySettings()
{
    //get the current wifi configuration
    WifiManager manager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration config = GetCurrentWifiConfiguration(manager);
    if(null == config)
        return;

    try
    {
        //get the link properties from the wifi configuration
        Object linkProperties = getField(config, "linkProperties");
        if(null == linkProperties)
            return;

        //get the setHttpProxy method for LinkProperties
        Class proxyPropertiesClass = Class.forName("android.net.ProxyProperties");
        Class[] setHttpProxyParams = new Class[1];
        setHttpProxyParams[0] = proxyPropertiesClass;
        Class lpClass = Class.forName("android.net.LinkProperties");
        Method setHttpProxy = lpClass.getDeclaredMethod("setHttpProxy", setHttpProxyParams);
        setHttpProxy.setAccessible(true);

        //get ProxyProperties constructor
        Class[] proxyPropertiesCtorParamTypes = new Class[3];
        proxyPropertiesCtorParamTypes[0] = String.class;
        proxyPropertiesCtorParamTypes[1] = int.class;
        proxyPropertiesCtorParamTypes[2] = String.class;

        Constructor proxyPropertiesCtor = proxyPropertiesClass.getConstructor(proxyPropertiesCtorParamTypes);

        //create the parameters for the constructor
        Object[] proxyPropertiesCtorParams = new Object[3];
        proxyPropertiesCtorParams[0] = "127.0.0.1";
        proxyPropertiesCtorParams[1] = 8118;
        proxyPropertiesCtorParams[2] = null;

        //create a new object using the params
        Object proxySettings = proxyPropertiesCtor.newInstance(proxyPropertiesCtorParams);

        //pass the new object to setHttpProxy
        Object[] params = new Object[1];
        params[0] = proxySettings;
        setHttpProxy.invoke(linkProperties, params);

        setProxySettings("STATIC", config);

        //save the settings
        manager.updateNetwork(config);
        manager.disconnect();
        manager.reconnect();
    }   
    catch(Exception e)
    {
    }
}
void unsetWifiProxySettings()
{
    WifiManager manager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration config = GetCurrentWifiConfiguration(manager);
    if(null == config)
        return;

    try
    {
        //get the link properties from the wifi configuration
        Object linkProperties = getField(config, "linkProperties");
        if(null == linkProperties)
            return;

        //get the setHttpProxy method for LinkProperties
        Class proxyPropertiesClass = Class.forName("android.net.ProxyProperties");
        Class[] setHttpProxyParams = new Class[1];
        setHttpProxyParams[0] = proxyPropertiesClass;
        Class lpClass = Class.forName("android.net.LinkProperties");
        Method setHttpProxy = lpClass.getDeclaredMethod("setHttpProxy", setHttpProxyParams);
        setHttpProxy.setAccessible(true);

        //pass null as the proxy
        Object[] params = new Object[1];
        params[0] = null;
        setHttpProxy.invoke(linkProperties, params);

        setProxySettings("NONE", config);

        //save the config
        manager.updateNetwork(config);
        manager.disconnect();
        manager.reconnect();
    }   
    catch(Exception e)
    {
    }
}
Carl
  • 256
  • 5
  • 10
  • what do you mean with "The settings do not seem to take effect with the disconnect/reconnect." ? – David Feb 03 '14 at 10:30
  • 1
    This is not working on Android 2.3.6 . Error : "No such field exception " Line : Object linkProperties = getField(config, "linkProperties"); in setWifiProxySettings() – Emre Koç Mar 23 '14 at 19:45
  • 1
    @carl i dont hv static option in proxy for my hp tablet 4.4 version there is only 2 option NONE and Manual can plz suggest how to do for manual? – KOTIOS Jul 11 '14 at 12:07
  • 1
    do you know if programmatically I can know if a wifi has services blockeds like whatsapp instagram, etc..? – Skizo-ozᴉʞS ツ Jul 22 '15 at 19:15
  • I had to add `manager.saveConfiguration();` as well and in addition, the `manager.reconnect();` connected to another configured WiFi - so take care ... ;) – Trinimon Nov 12 '15 at 14:30
  • Hi Carl I get an error "No such field exception " Line : Object linkProperties = getField(config, "linkProperties"). Could you please send me a sample code . Thank you very much . – Md Maidul Islam Mar 05 '17 at 06:47
  • The code attempts to call the setHttpProxy method on the linkPropertiesField object, which is of type Field. This does not work, since the Field class does not have this method. Instead, the method must be called on the LinkProperties object which is the value of this field. Get the field's value from the config object and call the method on that. The line has to look like this: `setHttpProxy.invoke(linkProperties.get(config), params);` – Markus Aug 16 '18 at 15:36
7

Similar to Dave's answer, but fewer lines by using only the method setProxy(ProxySettings settings, ProxyInfo proxy) (surrounding code omitted for clarity):

Class proxySettings = Class.forName("android.net.IpConfiguration$ProxySettings");

Class[] setProxyParams = new Class[2];
setProxyParams[0] = proxySettings;
setProxyParams[1] = ProxyInfo.class;

Method setProxy = config.getClass().getDeclaredMethod("setProxy", setProxyParams);
setProxy.setAccessible(true);

ProxyInfo desiredProxy = ProxyInfo.buildDirectProxy(YOUR_HOST, YOUR_PORT);

Object[] methodParams = new Object[2];
methodParams[0] = Enum.valueOf(proxySettings, "STATIC");
methodParams[1] = desiredProxy;

setProxy.invoke(config, methodParams);
thevoiceless
  • 93
  • 3
  • 4
  • This code works well but not in Android 8. E/WifiConfigManager: UID 10610 does not have permission to modify proxy Settings. What is workaround? – Degard Jul 24 '18 at 12:24
  • 1
    Android 8 added a public API to set the proxy, but restricts it to device owners and profile owners: https://developer.android.com/reference/android/net/wifi/WifiConfiguration#setHttpProxy(android.net.ProxyInfo). There does not appear to be a workaround. – Markus Aug 14 '18 at 15:34
  • How can I set wifi configurations in android 29 API? – Anant Shah May 11 '20 at 19:53
5

Here is some sample code to handle the same thing in Android 5.0 following the same format as Carl's answer above.

public void setWifiProxySettings5()
{
    //get the current wifi configuration
    WifiManager manager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration config = GetCurrentWifiConfiguration(manager);
    if(null == config)
        return;     

    try
    {       
        //linkProperties is no longer in WifiConfiguration          
        Class proxyInfoClass = Class.forName("android.net.ProxyInfo");
        Class[] setHttpProxyParams = new Class[1];
        setHttpProxyParams[0] = proxyInfoClass;         
        Class wifiConfigClass = Class.forName("android.net.wifi.WifiConfiguration");
        Method setHttpProxy = wifiConfigClass.getDeclaredMethod("setHttpProxy", setHttpProxyParams);
        setHttpProxy.setAccessible(true);

        //Method 1 to get the ENUM ProxySettings in IpConfiguration
        Class ipConfigClass = Class.forName("android.net.IpConfiguration");
        Field f = ipConfigClass.getField("proxySettings");
        Class proxySettingsClass = f.getType();        

        //Method 2 to get the ENUM ProxySettings in IpConfiguration
        //Note the $ between the class and ENUM
        //Class proxySettingsClass = Class.forName("android.net.IpConfiguration$ProxySettings");

        Class[] setProxySettingsParams = new Class[1];
        setProxySettingsParams[0] = proxySettingsClass;
        Method setProxySettings = wifiConfigClass.getDeclaredMethod("setProxySettings", setProxySettingsParams);
        setProxySettings.setAccessible(true);


        ProxyInfo pi = ProxyInfo.buildDirectProxy("127.0.0.1", 8118);
        //Android 5 supports a PAC file
        //ENUM value is "PAC"
        //ProxyInfo pacInfo = ProxyInfo.buildPacProxy(Uri.parse("http://localhost/pac"));

        //pass the new object to setHttpProxy
        Object[] params_SetHttpProxy = new Object[1];
        params_SetHttpProxy[0] = pi;
        setHttpProxy.invoke(config, params_SetHttpProxy);

        //pass the enum to setProxySettings
        Object[] params_setProxySettings = new Object[1];
        params_setProxySettings[0] = Enum.valueOf((Class<Enum>) proxySettingsClass, "STATIC");
        setProxySettings.invoke(config, params_setProxySettings);

        //save the settings
        manager.updateNetwork(config);
        manager.disconnect();
        manager.reconnect();
    }   
    catch(Exception e)
    {
        Log.v("wifiProxy", e.toString());
    }
}
Dave
  • 51
  • 1
  • 2
  • 1
    For Android 6 this code also works, BUT unfortunately you cannot update a network that you have not created yourself. This is because of the new Android Wifi rules: http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-network – radu122 Dec 09 '15 at 14:51