调试 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