首页
社区
课程
招聘
[原创]Android4.4 wifi代理流程
发表于: 2019-6-23 17:04 10782

[原创]Android4.4 wifi代理流程

2019-6-23 17:04
10782

举例,比如手机访问www.baidu.com,手机的ip为192.168.2.2,代理服务器的ip为192.168.3.4,端口为8087。

代理服务器这边socket监听8087端口,手机和代理服务器建立socket连接,把http请求的内容通过socket发送到代理服务器,代理服务器解析出Host。

得到host=www.baidu.com和port=80,然后解析www.baidu.com对应的ip=220.181.38.148,建立socket连接,把http请求的内容通过socket发送到220.181.38.148。同理把返回的内容发送回手机。

目前发现有两种代理方式,1是wifi代理,2是全局代理。

本来打算写全部的流程,但是从设置到wifi涉及到内容实在太多了,我追了两天,所以尽量列重点,忽略不重要到。

一般是设置中选择wifi长按,填入代理服务器,端口等。定位到实现代码
packages/apps/Settings/src/com/android/settings/wifi/WifiConfigController.java

关于远程调用,安卓系统很多都是基于binder,一般不直接调用binder,而是使用AIDL(接口定义语言)和ide工具生成封装好的代码。这里出现了一个新的远程调用的方式:Messenger。可能很多人不了解,因为一般只有系统framework有使用且使用不算多。本质上来说其实现也是基于binder实现跨进程调用,和AIDL个人总结有如下不同:
1:不用定义aidl文件。
2:Messenger只提供了一个方法进行进程间通信,send(Message msg)方法,发送一个Message,没有返回值,要拿到返回值,需要把client的Messenger作为msg.replyTo参数传递过去,service端处理完之后,在调用客户端的Messenger的send(Message msg)方法把返回值传递回client,这个过程是异步的。而AIDL你可以自己指定方法,指定返回值,它获取返回值是同步的。而AIDL调用默认是同步的,当然其实也可以异步。以上是针对客户端来说。
3:使用AIDL的时候,service端每收到一个client端的请求时,就会启动一个线程(非主线程)去执行相应的操作。而Messenger,service端收到的请求是放在Handler的MessageQueue里面,Handler大家都用过,它需要绑定一个Thread,然后不断poll message执行相关操作,这个过程是同步执行的。
4:Messenger需要和Handler绑定使用。
这里简单说下,有兴趣的可以自己写写例子熟悉使用。

WifiManager.java,sAsyncChanne内部封装的就是Messenger,就不展开了。

/frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java,获取WifiConfiguration,调用mWifiConfigStore.saveNetwork

WifiNative调用到wpa_ctrl,整个流程比较复杂。大概流程如下,把配置信息保存到wpa_supplicant,之后触发一些广播,主要的有:
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION和WifiManager.NETWORK_STATE_CHANGED_ACTION

/frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java注册了广播接收者

结合我们之前的dns流程一文,其中有个关键的类RouteSelector,

submit->//WifiSettings.java,新增wifi或者修改ip、代理等保存
== save->//WifiManager.java,内部封装Messenger远程调用
==== handleMessage->//WifiService.java,接收远程调用
====== sendMessage->//WifiStateMachine.java,获取WifiConfiguration
======== saveNetwork->//WifiConfigStore.java
========== addOrUpdateNetworkNative-> //新增或者更新wifi
============ writeIpAndProxyConfigurationsOnChange-> //把远程传进来的ip、代理等写入当前进程的WifiConfiguration
========== enableNetwork/saveConfig -> //把配置信息保存到wpa_supplicant,之后触发一些广播

handleConnectivityChange->接收处理LINK_CONFIGURATION_CHANGED_ACTION
handleConnect->接收处理NETWORK_STATE_CHANGED_ACTION
==== handleApplyDefaultProxy-> //全局代理的优先级应该比wifi代理高
====== sendProxyBroadcast-> //发送广播Proxy.PROXY_CHANGE_ACTION
======== broadcastIntentLocked->//接收处理Proxy.PROXY_CHANGE_ACTION,ActivityManagerService.java
========== setHttpProxy->//ApplicationThread的setHttpProxy,回到应用进程执行,ActivityThread.java
============ setHttpProxySystemProperty->//Proxy.java,设置java环境变量,存储http、https的代理host、port。

//应用进程启动情况下
handleBindApplication->//ActivityThread.java
== getProxy->//跨进程调用ConnectivityService.java
==== setHttpProxySystemProperty->//Proxy.java
====== setHttpProxySystemProperty->//Proxy.java

SettingsObserver->//ConnectivityService.java,监听Settings.Global.HTTP_PROXY
handleDeprecatedGlobalHttpProxy->//解析出host,port
==setGlobalProxy->//Settings.Global.GLOBAL_HTTP_PROXY_HOST存储host
====sendProxyBroadcast->//发送广播Proxy.PROXY_CHANGE_ACTION
======broadcastIntentLocked->//接收处理Proxy.PROXY_CHANGE_ACTION,ActivityManagerService.java
========setHttpProxy->//ApplicationThread的setHttpProxy,回到应用进程执行,ActivityThread.java
==========setHttpProxySystemProperty->//Proxy.java,设置java环境变量,存储http、https的代理host、port。

//应用进程启动情况下
handleBindApplication->//ActivityThread.java
==getProxy->//跨进程调用ConnectivityService.java
====setHttpProxySystemProperty->//Proxy.java
======setHttpProxySystemProperty->//Proxy.java

…略过
RouteSelector->//构造函数
==resetNextProxy->//根据uri获取代理
====select->//ProxySelectorImpl.java
======selectOneProxy->//解析url的请求类型,查找设置的java环境变量中的代理host和port
========lookupProxy->//返回proxy
==========nextProxy->//发起网络请求前先检查是否设置代理
============resetNextInetSocketAddress->//获取dns,如果有设置代理,替换host和port为代理服务器。

结合分析知道系统调用的是WifiManager.save(WifiConfiguration config, ActionListener listener),这是个隐藏方法,在sdk中无法直接引用,但是可以反射或者直接binder调用远程进程。

经过分析流程,发现其实主要是更新设置的代理到远程服务,而WifiManager有一个函数updateNetwork(WifiConfiguration config)可以实现该功能,而且还可以少构造一个参数。更新之后,怎么使其生效呢?还记得两个广播吗?我们想办法触发其中一个广播即可。
所以先断开连接再连接,触发广播,使代理立即生效。

代码如下:

添加权限
通过以上代码可以设置wifi代理,可以把其他应用的http(s)代理到设置的代理服务器。

检测代理和绕过代理以及反检测和反绕过待续。

当设置的代理无法连通时,会跳过代理。
HttpURLConnectionImpl.java

RouteSelector.java,把不能连通的ip加入路由表

举例,比如手机访问www.baidu.com,手机的ip为192.168.2.2,代理服务器的ip为192.168.3.4,端口为8087。

代理服务器这边socket监听8087端口,手机和代理服务器建立socket连接,把http请求的内容通过socket发送到代理服务器,代理服务器解析出Host。


得到host=www.baidu.com和port=80,然后解析www.baidu.com对应的ip=220.181.38.148,建立socket连接,把http请求的内容通过socket发送到220.181.38.148。同理把返回的内容发送回手机。

目前发现有两种代理方式,1是wifi代理,2是全局代理。


手机设置wifi代理

本来打算写全部的流程,但是从设置到wifi涉及到内容实在太多了,我追了两天,所以尽量列重点,忽略不重要到。

一般是设置中选择wifi长按,填入代理服务器,端口等。定位到实现代码
packages/apps/Settings/src/com/android/settings/wifi/WifiConfigController.java

    public WifiConfigController(
            WifiConfigUiBase parent, View view, AccessPoint accessPoint, boolean edit) {
            ...
            WifiInfo info = mAccessPoint.getInfo();
            if (info != null && info.getLinkSpeed() != -1) {
                addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
            }

            addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));

            boolean showAdvancedFields = false;
            if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
                WifiConfiguration config = mAccessPoint.getConfig();
                if (config.ipAssignment == IpAssignment.STATIC) {
                    mIpSettingsSpinner.setSelection(STATIC_IP);
                    showAdvancedFields = true;
                } else {
                    mIpSettingsSpinner.setSelection(DHCP);
                }
                //Display IP addresses
                for(InetAddress a : config.linkProperties.getAddresses()) {
                    addRow(group, R.string.wifi_ip_address, a.getHostAddress());
                }

                //构造函数,从设置中取出状态,是否设置代理
                if (config.proxySettings == ProxySettings.STATIC) {
                    mProxySettingsSpinner.setSelection(PROXY_STATIC);
                    showAdvancedFields = true;
                } else if (config.proxySettings == ProxySettings.PAC) {
                    mProxySettingsSpinner.setVisibility(View.GONE);
                    TextView textView = (TextView)mView.findViewById(R.id.proxy_pac_info);
                    textView.setVisibility(View.VISIBLE);
                    textView.setText(context.getString(R.string.proxy_url) +
                            config.linkProperties.getHttpProxy().getPacFileUrl());
                    showAdvancedFields = true;
                } else {
                    mProxySettingsSpinner.setSelection(PROXY_NONE);
                }
            }

            ...

    public WifiConfigController(
            WifiConfigUiBase parent, View view, AccessPoint accessPoint, boolean edit) {
            ...
            WifiInfo info = mAccessPoint.getInfo();
            if (info != null && info.getLinkSpeed() != -1) {
                addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
            }

            addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));

            boolean showAdvancedFields = false;
            if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
                WifiConfiguration config = mAccessPoint.getConfig();
                if (config.ipAssignment == IpAssignment.STATIC) {
                    mIpSettingsSpinner.setSelection(STATIC_IP);
                    showAdvancedFields = true;
                } else {
                    mIpSettingsSpinner.setSelection(DHCP);
                }
                //Display IP addresses
                for(InetAddress a : config.linkProperties.getAddresses()) {
                    addRow(group, R.string.wifi_ip_address, a.getHostAddress());
                }

                //构造函数,从设置中取出状态,是否设置代理
                if (config.proxySettings == ProxySettings.STATIC) {
                    mProxySettingsSpinner.setSelection(PROXY_STATIC);
                    showAdvancedFields = true;
                } else if (config.proxySettings == ProxySettings.PAC) {
                    mProxySettingsSpinner.setVisibility(View.GONE);
                    TextView textView = (TextView)mView.findViewById(R.id.proxy_pac_info);
                    textView.setVisibility(View.VISIBLE);
                    textView.setText(context.getString(R.string.proxy_url) +
                            config.linkProperties.getHttpProxy().getPacFileUrl());
                    showAdvancedFields = true;
                } else {
                    mProxySettingsSpinner.setSelection(PROXY_NONE);
                }
            }

            ...

当设置代理的时候,显示给用户
    //展示代理信息
    private void showProxyFields() {
        WifiConfiguration config = null;

        mView.findViewById(R.id.proxy_settings_fields).setVisibility(View.VISIBLE);

        if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
            config = mAccessPoint.getConfig();
        }

        if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) {
            mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.VISIBLE);
            mView.findViewById(R.id.proxy_fields).setVisibility(View.VISIBLE);
            if (mProxyHostView == null) {
                mProxyHostView = (TextView) mView.findViewById(R.id.proxy_hostname);
                mProxyHostView.addTextChangedListener(this);
                mProxyPortView = (TextView) mView.findViewById(R.id.proxy_port);
                mProxyPortView.addTextChangedListener(this);
                mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist);
                mProxyExclusionListView.addTextChangedListener(this);
            }
            if (config != null) {
                //获取设置过的代理信息
                ProxyProperties proxyProperties = config.linkProperties.getHttpProxy();
                if (proxyProperties != null) {
                    mProxyHostView.setText(proxyProperties.getHost());
                    mProxyPortView.setText(Integer.toString(proxyProperties.getPort()));
                    mProxyExclusionListView.setText(proxyProperties.getExclusionList());
                }
            }
        } else {
            mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.GONE);
            mView.findViewById(R.id.proxy_fields).setVisibility(View.GONE);
        }
    }
    
    
    
    //保存代理设置
        private boolean ipAndProxyFieldsAreValid() {
        mLinkProperties.clear();
        mIpAssignment = (mIpSettingsSpinner != null &&
                mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
                IpAssignment.STATIC : IpAssignment.DHCP;

        if (mIpAssignment == IpAssignment.STATIC) {
            int result = validateIpConfigFields(mLinkProperties);
            if (result != 0) {
                return false;
            }
        }

        mProxySettings = (mProxySettingsSpinner != null &&
                mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) ?
                ProxySettings.STATIC : ProxySettings.NONE;

        if (mProxySettings == ProxySettings.STATIC && mProxyHostView != null) {
            String host = mProxyHostView.getText().toString();
            String portStr = mProxyPortView.getText().toString();
            String exclusionList = mProxyExclusionListView.getText().toString();
            int port = 0;
            int result = 0;
            try {
                port = Integer.parseInt(portStr);
                //验证host和port是否正确
                result = ProxySelector.validate(host, portStr, exclusionList);
            } catch (NumberFormatException e) {
                result = R.string.proxy_error_invalid_port;
            }
            if (result == 0) {
                ProxyProperties proxyProperties= new ProxyProperties(host, port, exclusionList);
                mLinkProperties.setHttpProxy(proxyProperties);
            } else {
                return false;
            }
        }
        return true;
    }

    //展示代理信息
    private void showProxyFields() {
        WifiConfiguration config = null;

        mView.findViewById(R.id.proxy_settings_fields).setVisibility(View.VISIBLE);

        if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
            config = mAccessPoint.getConfig();
        }

        if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) {
            mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.VISIBLE);
            mView.findViewById(R.id.proxy_fields).setVisibility(View.VISIBLE);
            if (mProxyHostView == null) {
                mProxyHostView = (TextView) mView.findViewById(R.id.proxy_hostname);
                mProxyHostView.addTextChangedListener(this);
                mProxyPortView = (TextView) mView.findViewById(R.id.proxy_port);
                mProxyPortView.addTextChangedListener(this);
                mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist);
                mProxyExclusionListView.addTextChangedListener(this);
            }
            if (config != null) {
                //获取设置过的代理信息
                ProxyProperties proxyProperties = config.linkProperties.getHttpProxy();
                if (proxyProperties != null) {
                    mProxyHostView.setText(proxyProperties.getHost());
                    mProxyPortView.setText(Integer.toString(proxyProperties.getPort()));
                    mProxyExclusionListView.setText(proxyProperties.getExclusionList());
                }
            }
        } else {
            mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.GONE);
            mView.findViewById(R.id.proxy_fields).setVisibility(View.GONE);
        }
    }
    
    
    
    //保存代理设置
        private boolean ipAndProxyFieldsAreValid() {
        mLinkProperties.clear();
        mIpAssignment = (mIpSettingsSpinner != null &&
                mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
                IpAssignment.STATIC : IpAssignment.DHCP;

        if (mIpAssignment == IpAssignment.STATIC) {
            int result = validateIpConfigFields(mLinkProperties);
            if (result != 0) {
                return false;
            }
        }

        mProxySettings = (mProxySettingsSpinner != null &&
                mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) ?
                ProxySettings.STATIC : ProxySettings.NONE;

        if (mProxySettings == ProxySettings.STATIC && mProxyHostView != null) {
            String host = mProxyHostView.getText().toString();
            String portStr = mProxyPortView.getText().toString();
            String exclusionList = mProxyExclusionListView.getText().toString();
            int port = 0;
            int result = 0;
            try {
                port = Integer.parseInt(portStr);
                //验证host和port是否正确
                result = ProxySelector.validate(host, portStr, exclusionList);
            } catch (NumberFormatException e) {
                result = R.string.proxy_error_invalid_port;
            }
            if (result == 0) {
                ProxyProperties proxyProperties= new ProxyProperties(host, port, exclusionList);
                mLinkProperties.setHttpProxy(proxyProperties);
            } else {
                return false;
            }
        }
        return true;
    }

保存和获取都是通过LinkProperties操作ProxyProperties,而ProxyProperties只是赋值和获取,没有其他操作。
    public void setHttpProxy(ProxyProperties proxy) {
        mHttpProxy = proxy;
    }
    public ProxyProperties getHttpProxy() {
        return mHttpProxy;
    }

    public void setHttpProxy(ProxyProperties proxy) {
        mHttpProxy = proxy;
    }
    public ProxyProperties getHttpProxy() {
        return mHttpProxy;
    }

WifiConfigController属于WifiDialog,WifiDialog 是我们长按时弹出到设置ip、代理等的窗口。WifiDialog 属于packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java

    //当添加新的网络或者编辑保存触发,远程调用mWifiManager.save
    /* package */ void submit(WifiConfigController configController) {

        final WifiConfiguration config = configController.getConfig();

        if (config == null) {
            if (mSelectedAccessPoint != null
                    && mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
                mWifiManager.connect(mSelectedAccessPoint.networkId,
                        mConnectListener);
            }
        } else if (config.networkId != INVALID_NETWORK_ID) {
            if (mSelectedAccessPoint != null) {
                mWifiManager.save(config, mSaveListener);
            }
        } else {
            if (configController.isEdit()) {
                mWifiManager.save(config, mSaveListener);
            } else {
                mWifiManager.connect(config, mConnectListener);
            }
        }

        if (mWifiManager.isWifiEnabled()) {
            mScanner.resume();
        }
        updateAccessPoints();
    }

    //当添加新的网络或者编辑保存触发,远程调用mWifiManager.save
    /* package */ void submit(WifiConfigController configController) {

        final WifiConfiguration config = configController.getConfig();

        if (config == null) {
            if (mSelectedAccessPoint != null
                    && mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
                mWifiManager.connect(mSelectedAccessPoint.networkId,
                        mConnectListener);
            }
        } else if (config.networkId != INVALID_NETWORK_ID) {
            if (mSelectedAccessPoint != null) {
                mWifiManager.save(config, mSaveListener);
            }
        } else {
            if (configController.isEdit()) {
                mWifiManager.save(config, mSaveListener);
            } else {
                mWifiManager.connect(config, mConnectListener);
            }
        }

        if (mWifiManager.isWifiEnabled()) {
            mScanner.resume();
        }
        updateAccessPoints();
    }

关于远程调用,安卓系统很多都是基于binder,一般不直接调用binder,而是使用AIDL(接口定义语言)和ide工具生成封装好的代码。这里出现了一个新的远程调用的方式:Messenger。可能很多人不了解,因为一般只有系统framework有使用且使用不算多。本质上来说其实现也是基于binder实现跨进程调用,和AIDL个人总结有如下不同:
1:不用定义aidl文件。
2:Messenger只提供了一个方法进行进程间通信,send(Message msg)方法,发送一个Message,没有返回值,要拿到返回值,需要把client的Messenger作为msg.replyTo参数传递过去,service端处理完之后,在调用客户端的Messenger的send(Message msg)方法把返回值传递回client,这个过程是异步的。而AIDL你可以自己指定方法,指定返回值,它获取返回值是同步的。而AIDL调用默认是同步的,当然其实也可以异步。以上是针对客户端来说。
3:使用AIDL的时候,service端每收到一个client端的请求时,就会启动一个线程(非主线程)去执行相应的操作。而Messenger,service端收到的请求是放在Handler的MessageQueue里面,Handler大家都用过,它需要绑定一个Thread,然后不断poll message执行相关操作,这个过程是同步执行的。
4:Messenger需要和Handler绑定使用。
这里简单说下,有兴趣的可以自己写写例子熟悉使用。

WifiManager.java,sAsyncChanne内部封装的就是Messenger,就不展开了。


    public void save(WifiConfiguration config, ActionListener listener) {
        if (config == null) throw new IllegalArgumentException("config cannot be null");
        validateChannel();
        sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
    }

    public void save(WifiConfiguration config, ActionListener listener) {
        if (config == null) throw new IllegalArgumentException("config cannot be null");
        validateChannel();
        sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
    }

远程调用frameworks/base/services/java/com/android/server/wifi/WifiService.java,调用mWifiStateMachine.sendMessage
                case WifiManager.CONNECT_NETWORK:
                case WifiManager.SAVE_NETWORK: {
                    WifiConfiguration config = (WifiConfiguration) msg.obj;
                    int networkId = msg.arg1;
                    if (config != null && config.isValid()) {
                        // This is restricted because there is no UI for the user to
                        // monitor/control PAC.
                        if (config.proxySettings != ProxySettings.PAC) {
                            if (DBG) Slog.d(TAG, "Connect with config" + config);
                            //继续传递msg
                            mWifiStateMachine.sendMessage(Message.obtain(msg));
                        } else {
                            Slog.e(TAG,  "ClientHandler.handleMessage cannot process msg with PAC");
                            if (msg.what == WifiManager.CONNECT_NETWORK) {
                                replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
                            } else {
                                replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
                            }
                        }
                    } else if (config == null
                            && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
                        if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
                        mWifiStateMachine.sendMessage(Message.obtain(msg));
                    } else {
                        Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
                        if (msg.what == WifiManager.CONNECT_NETWORK) {
                            replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
                        } else {
                            replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
                        }
                    }
                    break;
                }

                case WifiManager.CONNECT_NETWORK:
                case WifiManager.SAVE_NETWORK: {
                    WifiConfiguration config = (WifiConfiguration) msg.obj;
                    int networkId = msg.arg1;
                    if (config != null && config.isValid()) {
                        // This is restricted because there is no UI for the user to
                        // monitor/control PAC.
                        if (config.proxySettings != ProxySettings.PAC) {
                            if (DBG) Slog.d(TAG, "Connect with config" + config);
                            //继续传递msg
                            mWifiStateMachine.sendMessage(Message.obtain(msg));
                        } else {
                            Slog.e(TAG,  "ClientHandler.handleMessage cannot process msg with PAC");
                            if (msg.what == WifiManager.CONNECT_NETWORK) {
                                replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
                            } else {
                                replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
                            }
                        }
                    } else if (config == null
                            && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
                        if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
                        mWifiStateMachine.sendMessage(Message.obtain(msg));
                    } else {
                        Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
                        if (msg.what == WifiManager.CONNECT_NETWORK) {
                            replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED);
                        } else {
                            replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED);
                        }
                    }
                    break;
                }

/frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java,获取WifiConfiguration,调用mWifiConfigStore.saveNetwork

                case WifiManager.SAVE_NETWORK:
                    config = (WifiConfiguration) message.obj;
                    NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
                    if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
                        replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
                    } else {
                        loge("Failed to save network");
                        replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
                                WifiManager.ERROR);
                    }
                    break;

                case WifiManager.SAVE_NETWORK:
                    config = (WifiConfiguration) message.obj;
                    NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
                    if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
                        replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
                    } else {
                        loge("Failed to save network");
                        replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
                                WifiManager.ERROR);
                    }
                    break;

/frameworks/base/wifi/java/android/net/wifi/WifiConfigStore.java
    NetworkUpdateResult saveNetwork(WifiConfiguration config) {
        if (VDBG) localLog("saveNetwork", config.networkId);
        // A new network cannot have null SSID
        if (config == null || (config.networkId == INVALID_NETWORK_ID &&
                config.SSID == null)) {
            return new NetworkUpdateResult(INVALID_NETWORK_ID);
        }

        boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
        //新增或者更新
        NetworkUpdateResult result = addOrUpdateNetworkNative(config);
        int netId = result.getNetworkId();
        /* enable a new network */
        if (newNetwork && netId != INVALID_NETWORK_ID) {
            //新增wifi,断开的当前连接的wifi,再连接指定wifi
            mWifiNative.enableNetwork(netId, false);
            mConfiguredNetworks.get(netId).status = Status.ENABLED;
        }
        //mWifiNative的调用会到wpa_ctrl,很复杂,就不列出了
        mWifiNative.saveConfig();
        sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
                WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
        return result;
    }
    
    //主要是保存ip、代理
    private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {
        ...
        //获取当前连接
        WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
        if (currentConfig == null) {
            currentConfig = new WifiConfiguration();
            currentConfig.ipAssignment = IpAssignment.DHCP;
            currentConfig.proxySettings = ProxySettings.NONE;
            currentConfig.networkId = netId;
        }

        readNetworkVariables(currentConfig);

        mConfiguredNetworks.put(netId, currentConfig);
        mNetworkIds.put(configKey(currentConfig), netId);
        
        //把远程传进来的ip、代理等写入当前进程的WifiConfiguration
        NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
        result.setIsNewNetwork(newNetwork);
        result.setNetworkId(netId);
        return result;
    }

    NetworkUpdateResult saveNetwork(WifiConfiguration config) {
        if (VDBG) localLog("saveNetwork", config.networkId);
        // A new network cannot have null SSID
        if (config == null || (config.networkId == INVALID_NETWORK_ID &&
                config.SSID == null)) {
            return new NetworkUpdateResult(INVALID_NETWORK_ID);
        }

        boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
        //新增或者更新
        NetworkUpdateResult result = addOrUpdateNetworkNative(config);
        int netId = result.getNetworkId();
        /* enable a new network */
        if (newNetwork && netId != INVALID_NETWORK_ID) {
            //新增wifi,断开的当前连接的wifi,再连接指定wifi
            mWifiNative.enableNetwork(netId, false);
            mConfiguredNetworks.get(netId).status = Status.ENABLED;
        }
        //mWifiNative的调用会到wpa_ctrl,很复杂,就不列出了
        mWifiNative.saveConfig();
        sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
                WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
        return result;
    }
    
    //主要是保存ip、代理
    private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {
        ...
        //获取当前连接
        WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
        if (currentConfig == null) {
            currentConfig = new WifiConfiguration();
            currentConfig.ipAssignment = IpAssignment.DHCP;
            currentConfig.proxySettings = ProxySettings.NONE;
            currentConfig.networkId = netId;
        }

        readNetworkVariables(currentConfig);

        mConfiguredNetworks.put(netId, currentConfig);
        mNetworkIds.put(configKey(currentConfig), netId);
        
        //把远程传进来的ip、代理等写入当前进程的WifiConfiguration
        NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
        result.setIsNewNetwork(newNetwork);
        result.setNetworkId(netId);
        return result;
    }

WifiNative调用到wpa_ctrl,整个流程比较复杂。大概流程如下,把配置信息保存到wpa_supplicant,之后触发一些广播,主要的有:
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION和WifiManager.NETWORK_STATE_CHANGED_ACTION

/frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java注册了广播接收者


    private class WifiStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                ...
                Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
                        new NetworkInfo(mNetworkInfo));
                msg.sendToTarget();
            } else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
                mLinkProperties = intent.getParcelableExtra(WifiManager.EXTRA_LINK_PROPERTIES);
                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
                msg.sendToTarget();
            }
        }
    }

    private class WifiStateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                ...
                Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
                        new NetworkInfo(mNetworkInfo));
                msg.sendToTarget();
            } else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
                mLinkProperties = intent.getParcelableExtra(WifiManager.EXTRA_LINK_PROPERTIES);
                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
                msg.sendToTarget();
            }
        }
    }


frameworks/base/services/java/com/android/server/ConnectivityService.java内
    private static class DefaultNetworkFactory implements NetworkFactory {
        ...
        @Override
        public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
            switch (config.radio) {
                case TYPE_WIFI:
                    return new WifiStateTracker(targetNetworkType, config.name);
                ...
            }
        }
    }
    
    //构造函数内
            try {
                tracker = netFactory.createTracker(targetNetworkType, config);
                mNetTrackers[targetNetworkType] = tracker;
            } catch (IllegalArgumentException e) {
                Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
                        + " tracker: " + e);
                continue;
            }

            tracker.startMonitoring(context, mTrackerHandler);

    private static class DefaultNetworkFactory implements NetworkFactory {
        ...
        @Override
        public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
            switch (config.radio) {
                case TYPE_WIFI:
                    return new WifiStateTracker(targetNetworkType, config.name);
                ...
            }
        }
    }
    
    //构造函数内
            try {
                tracker = netFactory.createTracker(targetNetworkType, config);
                mNetTrackers[targetNetworkType] = tracker;
            } catch (IllegalArgumentException e) {
                Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
                        + " tracker: " + e);
                continue;
            }

            tracker.startMonitoring(context, mTrackerHandler);

内部类
    private class NetworkStateTrackerHandler extends Handler {
        public NetworkStateTrackerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            NetworkInfo info;
            switch (msg.what) {
                case NetworkStateTracker.EVENT_STATE_CHANGED: {
                    info = (NetworkInfo) msg.obj;
                    NetworkInfo.State state = info.getState();
                    ...
                    } else if (state == NetworkInfo.State.CONNECTED) {
                        //调用handleConnectivityChange
                        handleConnect(info);
                    }
                    if (mLockdownTracker != null) {
                        mLockdownTracker.onNetworkInfoChanged(info);
                    }
                    break;
                }
                case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
                    info = (NetworkInfo) msg.obj;
                    handleConnectivityChange(info.getType(), false);
                    break;
                }
                ...
                }
            }
        }
    }
    

    //EVENT_CONFIGURATION_CHANGED和EVENT_STATE_CHANGED最后都会调用到
    private void handleConnectivityChange(int netType, boolean doReset) {
        ...
        if (mNetConfigs[netType].isDefault()) {
                handleApplyDefaultProxy(newLp.getHttpProxy());
            }
        ...
    }
    
    
    //所以应该全局代理的优先级比wifi代理高
    private void handleApplyDefaultProxy(ProxyProperties proxy) {
    ...
            if (mGlobalProxy != null) return;
            if (!mDefaultProxyDisabled) {
                sendProxyBroadcast(proxy);
            }
        }
    }
    
    
    //从这里和后面的全局代理有重叠,就不继续了
    private void sendProxyBroadcast(ProxyProperties proxy) {
        if (proxy == null) proxy = new ProxyProperties("", 0, "");
        if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
        if (DBG) log("sending Proxy Broadcast for " + proxy);
        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
        final long ident = Binder.clearCallingIdentity();
        try {
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    

    private class NetworkStateTrackerHandler extends Handler {
        public NetworkStateTrackerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            NetworkInfo info;
            switch (msg.what) {
                case NetworkStateTracker.EVENT_STATE_CHANGED: {
                    info = (NetworkInfo) msg.obj;
                    NetworkInfo.State state = info.getState();
                    ...
                    } else if (state == NetworkInfo.State.CONNECTED) {
                        //调用handleConnectivityChange
                        handleConnect(info);
                    }
                    if (mLockdownTracker != null) {
                        mLockdownTracker.onNetworkInfoChanged(info);
                    }
                    break;
                }
                case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
                    info = (NetworkInfo) msg.obj;
                    handleConnectivityChange(info.getType(), false);
                    break;
                }
                ...
                }
            }
        }
    }
    

    //EVENT_CONFIGURATION_CHANGED和EVENT_STATE_CHANGED最后都会调用到
    private void handleConnectivityChange(int netType, boolean doReset) {
        ...
        if (mNetConfigs[netType].isDefault()) {
                handleApplyDefaultProxy(newLp.getHttpProxy());
            }
        ...
    }
    
    
    //所以应该全局代理的优先级比wifi代理高
    private void handleApplyDefaultProxy(ProxyProperties proxy) {
    ...
            if (mGlobalProxy != null) return;
            if (!mDefaultProxyDisabled) {
                sendProxyBroadcast(proxy);
            }
        }
    }
    
    
    //从这里和后面的全局代理有重叠,就不继续了
    private void sendProxyBroadcast(ProxyProperties proxy) {
        if (proxy == null) proxy = new ProxyProperties("", 0, "");
        if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
        if (DBG) log("sending Proxy Broadcast for " + proxy);
        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
        final long ident = Binder.clearCallingIdentity();
        try {
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    

wifi代理分析到sendProxyBroadcast,因为后面的流程和全局代理一致。

通过设置Settings.Global.GLOBAL_HTTP_PROXY_HOST/Settings.Global.HTTP_PROXY代理

在frameworks/base/services/java/com/android/server/ConnectivityService.java中注册了监听器
    //注册监听器
        mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
        mSettingsObserver.observe(mContext);

    //实现
    private static class SettingsObserver extends ContentObserver {
        private int mWhat;
        private Handler mHandler;
        SettingsObserver(Handler handler, int what) {
            super(handler);
            mHandler = handler;
            mWhat = what;
        }

        void observe(Context context) {
            ContentResolver resolver = context.getContentResolver();
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.HTTP_PROXY), false, this);
        }

    //当修改Settings.Global.HTTP_PROXY时触发
        @Override
        public void onChange(boolean selfChange) {
            mHandler.obtainMessage(mWhat).sendToTarget();
        }
    }
    
    //内部handler的部分代码
    case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
                    handleDeprecatedGlobalHttpProxy();
                    break;
                }
    
    //取出设置的http代理,封装
    private void handleDeprecatedGlobalHttpProxy() {
        String proxy = Settings.Global.getString(mContext.getContentResolver(),
                Settings.Global.HTTP_PROXY);
        if (!TextUtils.isEmpty(proxy)) {
            String data[] = proxy.split(":");
            if (data.length == 0) {
                return;
            }

            String proxyHost =  data[0];
            int proxyPort = 8080;
            if (data.length > 1) {
                try {
                    proxyPort = Integer.parseInt(data[1]);
                } catch (NumberFormatException e) {
                    return;
                }
            }
            ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
            setGlobalProxy(p);
        }
    }
    
    
    //解析出host和port,用Settings.Global.GLOBAL_HTTP_PROXY_HOST存储
    public void setGlobalProxy(ProxyProperties proxyProperties) {
        enforceConnectivityInternalPermission();

        synchronized (mProxyLock) {
            if (proxyProperties == mGlobalProxy) return;
            if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
            if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;

            String host = "";
            int port = 0;
            String exclList = "";
            String pacFileUrl = "";
            if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
                    !TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) {
                if (!proxyProperties.isValid()) {
                    if (DBG)
                        log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
                    return;
                }
                mGlobalProxy = new ProxyProperties(proxyProperties);
                host = mGlobalProxy.getHost();
                port = mGlobalProxy.getPort();
                exclList = mGlobalProxy.getExclusionList();
                if (proxyProperties.getPacFileUrl() != null) {
                    pacFileUrl = proxyProperties.getPacFileUrl();
                }
            } else {
                mGlobalProxy = null;
            }
            ContentResolver res = mContext.getContentResolver();
            final long token = Binder.clearCallingIdentity();
            try {
                //保存host和port
                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
                Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                        exclList);
                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if (mGlobalProxy == null) {
            proxyProperties = mDefaultProxy;
        }
        //发送通知
        sendProxyBroadcast(proxyProperties);
    }
    
 
     //发送广播Proxy.PROXY_CHANGE_ACTION
    private void sendProxyBroadcast(ProxyProperties proxy) {
        if (proxy == null) proxy = new ProxyProperties("", 0, "");
        if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
        if (DBG) log("sending Proxy Broadcast for " + proxy);
        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
        final long ident = Binder.clearCallingIdentity();
        try {
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    } 

    //注册监听器
        mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
        mSettingsObserver.observe(mContext);

    //实现
    private static class SettingsObserver extends ContentObserver {
        private int mWhat;
        private Handler mHandler;
        SettingsObserver(Handler handler, int what) {
            super(handler);
            mHandler = handler;
            mWhat = what;
        }

        void observe(Context context) {
            ContentResolver resolver = context.getContentResolver();
            resolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.HTTP_PROXY), false, this);
        }

    //当修改Settings.Global.HTTP_PROXY时触发
        @Override
        public void onChange(boolean selfChange) {
            mHandler.obtainMessage(mWhat).sendToTarget();
        }
    }
    
    //内部handler的部分代码
    case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
                    handleDeprecatedGlobalHttpProxy();
                    break;
                }
    
    //取出设置的http代理,封装
    private void handleDeprecatedGlobalHttpProxy() {
        String proxy = Settings.Global.getString(mContext.getContentResolver(),
                Settings.Global.HTTP_PROXY);
        if (!TextUtils.isEmpty(proxy)) {
            String data[] = proxy.split(":");
            if (data.length == 0) {
                return;
            }

            String proxyHost =  data[0];
            int proxyPort = 8080;
            if (data.length > 1) {
                try {
                    proxyPort = Integer.parseInt(data[1]);
                } catch (NumberFormatException e) {
                    return;
                }
            }
            ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
            setGlobalProxy(p);
        }
    }
    
    
    //解析出host和port,用Settings.Global.GLOBAL_HTTP_PROXY_HOST存储
    public void setGlobalProxy(ProxyProperties proxyProperties) {
        enforceConnectivityInternalPermission();

        synchronized (mProxyLock) {
            if (proxyProperties == mGlobalProxy) return;
            if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
            if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;

            String host = "";
            int port = 0;
            String exclList = "";
            String pacFileUrl = "";
            if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
                    !TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) {
                if (!proxyProperties.isValid()) {
                    if (DBG)
                        log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
                    return;
                }
                mGlobalProxy = new ProxyProperties(proxyProperties);
                host = mGlobalProxy.getHost();
                port = mGlobalProxy.getPort();
                exclList = mGlobalProxy.getExclusionList();
                if (proxyProperties.getPacFileUrl() != null) {
                    pacFileUrl = proxyProperties.getPacFileUrl();
                }
            } else {
                mGlobalProxy = null;
            }
            ContentResolver res = mContext.getContentResolver();
            final long token = Binder.clearCallingIdentity();
            try {
                //保存host和port
                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
                Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                        exclList);
                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if (mGlobalProxy == null) {
            proxyProperties = mDefaultProxy;
        }
        //发送通知
        sendProxyBroadcast(proxyProperties);
    }
    
 
     //发送广播Proxy.PROXY_CHANGE_ACTION
    private void sendProxyBroadcast(ProxyProperties proxy) {
        if (proxy == null) proxy = new ProxyProperties("", 0, "");
        if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
        if (DBG) log("sending Proxy Broadcast for " + proxy);
        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
        final long ident = Binder.clearCallingIdentity();
        try {
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    } 

调用
frameworks/base/core/java/android/app/ContextImpl.java

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2019-6-23 17:18 被卓桐编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (6)
雪    币: 6369
活跃值: (1688)
能力值: ( LV4,RANK:156 )
在线值:
发帖
回帖
粉丝
2
dalao辛苦,感谢分享
2019-6-24 14:27
0
雪    币: 1216
活跃值: (230)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
dalao,android 6.0以上可以http代理吗
2019-6-26 15:30
0
雪    币: 6737
活跃值: (796)
能力值: ( LV13,RANK:393 )
在线值:
发帖
回帖
粉丝
4
weishi dalao,android 6.0以上可以http代理吗
应该是不可以了,我抽时间看看吧,看有没有绕过的方法
2019-6-28 23:26
0
雪    币: 220
活跃值: (1223)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
5

很详细,赞一个! 不过android4.4.4原生系统我做了几个实验,用如下方式在程序中设置代理为抓包软件主机地址,然后HttpsUrlConnection缺省参数连接(不指定代理参数),但是都抓不到包,请问是什么原因?
1. 直接用System.setProperty设置http[s].proxyHost代理,然后用代理软件抓不到包,设置代理无效。
2. 用ProxySelector.setDefault替换系统的默认的,并设置select函数指向我代理地址,代理软件也抓不到包。
以上两种代理方式对HttpsUrlConnection默认参数是无效的(试了okhttp3.11.0缺省参数okhttpclieck连接上面两种方式代理设置抓包都有效),请问是什么原因啊? 按照源码的理解是会调用ProxySelector.getDefault获取缺省选择器,而缺省选择器最后会调用selectOneProxy-》lookupProxy-》System.getProperty来获取代理的啊?

最后于 2020-9-27 16:44 被cjycjw编辑 ,原因:
2020-9-27 16:41
0
雪    币: 3561
活跃值: (541)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6

GOOD

最后于 2020-9-27 16:48 被朱年吉祥编辑 ,原因:
2020-9-27 16:48
0
雪    币: 220
活跃值: (1223)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
7
cjycjw 很详细,赞一个! 不过android4.4.4原生系统我做了几个实验,用如下方式在程序中设置代理为抓包软件主机地址,然后HttpsUrlConnection缺省参数连接(不指定代理参 ...

知道原因了,可能是connect pool之类的影响,本人用了同一个url地址只是参数不同, 为了测试先直接连接,然后设置代理属性,再次连接,这种情况会复用之前的连接,导致不走代理,从而导致设置的代理无效。注意这个跟响应缓存没有关系,即使加上_=time参数或setUseCaches(false)也是同样问题。

最后于 2020-9-27 17:45 被cjycjw编辑 ,原因:
2020-9-27 17:42
0
游客
登录 | 注册 方可回帖
返回
//