模拟器adb 修改手机代理方式

调试 Android app 时用 Charles 做代理的场景成了非常常见的操作,而让人烦恼的是,每次都需要进入手机的 WiFi -> 点击当前 WiFi -> 点击编辑 -> 点击 Advanced options -> proxy 选择 None 或者 Manual -> 上一步如果选了 Manual, 则需要输入 IP 地址和端口号 -> 保存。

这样一个六七步的步骤,真的很让人烦,而如果电脑的局域网 IP 地址不固定的话,就更加让人不爽了,意味着每次电脑重新联网后,手机都需要重新设置代理的 IP。就算电脑 IP 固定,当手机需要使用 Charles 代理或者关闭代理,都比较麻烦。所以很久前我就想有没有方法可以一键设置代理。

我的构想是,如果电脑 IP 地址不固定,那么一键设置需要在电脑上操作,不然无法获知电脑的 IP,当然也可以电脑运行个 socket server,然后手机连接,然后电脑把 IP 发给手机。如果电脑 IP 地址固定,最理想的则是手机上一键设置,这样就不需要 adb 连接了。

经过一番 google 和惨痛的尝试,我得知了两种并不完美的方法。

方法一:

/**
     * 设置代理信息 exclList是添加不用代理的网址用的
     * */
    public static void setHttpProxySetting(Context context, String host, int port)
            throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
            IllegalAccessException, NoSuchFieldException {
        WifiManager wifiManager =(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
        WifiConfiguration config = getCurrentWifiConfiguration(wifiManager);
        ProxyInfo mInfo = ProxyInfo.buildDirectProxy(host,port);
        if (config != null){
            Class clazz = Class.forName("android.net.wifi.WifiConfiguration");
            Class parmars = Class.forName("android.net.ProxyInfo");
            Method method = clazz.getMethod("setHttpProxy",parmars);
            method.invoke(config,mInfo);
            Object mIpConfiguration = getDeclaredFieldObject(config,"mIpConfiguration");

            setEnumField(mIpConfiguration, "STATIC", "proxySettings");
            setDeclardFildObject(config,"mIpConfiguration", mIpConfiguration);
            
            // save the settings
            wifiManager.updateNetwork(config);
            wifiManager.disconnect();
            wifiManager.reconnect();
        }

    }
    /**
     * 取消代理设置
     * */
    public static void unSetHttpProxy(Context context)
            throws ClassNotFoundException, InvocationTargetException, IllegalAccessException,
            NoSuchFieldException, NoSuchMethodException {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiConfiguration configuration = getCurrentWifiConfiguration(wifiManager);
        ProxyInfo mInfo = ProxyInfo.buildDirectProxy(null, 0);
        if (configuration != null){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                configuration.setHttpProxy(mInfo);
            } else {
                Class clazz = Class.forName("android.net.wifi.WifiConfiguration");
                Class parmars = Class.forName("android.net.ProxyInfo");
                Method method = clazz.getMethod("setHttpProxy",parmars);
                method.invoke(configuration,mInfo);
                Object mIpConfiguration = getDeclaredFieldObject(configuration,"mIpConfiguration");
                setEnumField(mIpConfiguration, "NONE", "proxySettings");
                setDeclardFildObject(configuration,"mIpConfiguration",mIpConfiguration);
            }
            
            wifiManager.updateNetwork(configuration);
            wifiManager.disconnect(); 
            wifiManager.reconnect();
        }
    }

 

上面的方法直接获取到当前连接的 WiFi configuration,然后把它的 http proxy 类型 (枚举变量,主要是 NONE 和 STATIC 两个值),和值 (即 IP 和 port) 用反射的方法设置进去,然后更新 WiFi configuration,并断开 WiFi 并重新连接 WiFi。以上设置代理和关闭代理的动作,全部由上面的代码一键完成,直接在手机上运行即可,并且代码运行结果和手机 Settings 中的 UI 结果是一致的,感觉相当完美。

然而方法一不支持 API 23 以上的 Android 系统,而所用 API 21 测试是可以完美运行的,在如今 API 28 都发布了的时候,不支持 API 23 以上可以说让实用性大打折扣。不过这是可以理解的,毕竟处于安全考虑,不能让用户的手机随便被第三方 app 默默修改了代理,这太危险了。

方法二:

1
adb shell settings put global http_proxy <ip>:<port>

执行以上命令后,Settings 中的 UI 并未更改,但是代理已经生效。这一方法实际是新增了 Settings Provider 中的 key value,有两种方式可以查看到这一新增 key value:

1
2
3
adb shell settings get global http_proxy
adb shell settings get global global_http_proxy_host
adb shell settings get global global_http_proxy_port

一、使用adb修改手机代理方式
设置代理:

adb shell settings put global http_proxy 代理IP地址:端口号

如:

adb shell settings put global http_proxy 127.0.0.1:8888

移除代理:

adb shell settings delete global http_proxy

adb shell settings delete global global_http_proxy_host

adb shell settings delete global global_http_proxy_port

adb reboot

二、使用第三方apk
AndroidProxySetter工具可以帮助我们使用adb命令可以快速进行wifi代理的设置和清除
GitHub地址:

https://github.com/jpkrause/AndroidProxySetter
下好apk后,安装到手机

adb install proxy-setter-debug-0.2.1.apk

设置代理:

adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e host 代理IP地址 -e port 端口号 -e ssid WIFI名称 -e reset-wifi true -e key WIFI密码

如:

adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e host 127.0.0.1 -e port 8888 -e ssid YOUR-WIFI-NAME -e reset-wifi true -e key YOUR-WIFI-PASSWORD

赞 (0)