【问题标题】:Android WebView set proxy programmatically on Android-LAndroid WebView 在 Android-L 上以编程方式设置代理
【发布时间】:2014-08-12 19:21:39
【问题描述】:

所以this solution 可以在 Android 4.4.4 上运行,但是,代码在 Android-L 开发人员预览版中停止工作,有人有一些适用于 Android-L 的代码吗?或者关于我自己如何获取代码的任何提示?

这是我用于 KitKat 的当前方法(并且有效)

@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean setKitKatWebViewProxy(WebView webView, String host, int port) {
    Context appContext = webView.getContext().getApplicationContext();
    System.setProperty("http.proxyHost", host);
    System.setProperty("http.proxyPort", port + "");
    System.setProperty("https.proxyHost", host);
    System.setProperty("https.proxyPort", port + "");
    try {
        Class applictionCls = Class.forName(FinalVariables.APPLICATION_CANONICAL_NAME);
        Field loadedApkField = applictionCls.getField("mLoadedApk");
        loadedApkField.setAccessible(true);
        Object loadedApk = loadedApkField.get(appContext);
        Class loadedApkCls = Class.forName("android.app.LoadedApk");
        Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
        receiversField.setAccessible(true);
        ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
        for (Object receiverMap : receivers.values()) {
            for (Object rec : ((ArrayMap) receiverMap).keySet()) {
                Class clazz = rec.getClass();
                if (clazz.getName().contains("ProxyChangeListener")) {
                    Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
                    Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);

                    /*********** optional, may be need in future *************/
                    final String CLASS_NAME = "android.net.ProxyProperties";
                    Class cls = Class.forName(CLASS_NAME);
                    Constructor constructor = cls.getConstructor(String.class, Integer.TYPE, String.class);
                    constructor.setAccessible(true);
                    Object proxyProperties = constructor.newInstance(host, port, null);
                    intent.putExtra("proxy", (Parcelable) proxyProperties);
                    /*********** optional, may be need in future *************/

                    onReceiveMethod.invoke(rec, appContext, intent);
                }
            }
        }
        return true;
    } catch (ClassNotFoundException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    } catch (NoSuchFieldException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    } catch (IllegalAccessException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    } catch (IllegalArgumentException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    } catch (NoSuchMethodException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    } catch (InvocationTargetException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    } catch (InstantiationException e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        String exceptionAsString = sw.toString();
        Log.v(LOG_TAG, e.getMessage());
        Log.v(LOG_TAG, exceptionAsString);
    }
    return false;
}

谢谢!

【问题讨论】:

    标签: android-webview android-5.0-lollipop


    【解决方案1】:

    删除我的previous solusion for kitkat 的可选块应该可以在 android L-preview 上运行,因为 ProxyProperties 类在 android L-preview 中再也找不到了。 所以新的解决方案是:

    public static void setLPreViewWebViewProxy(Context context, String host, int port) {
        System.setProperty("http.proxyHost", host);
        System.setProperty("http.proxyPort", port + "");
        try {
            Context appContext = context.getApplicationContext();
            Class applictionClass = Class.forName("android.app.Application");
            Field mLoadedApkField = applictionClass.getDeclaredField("mLoadedApk");
            mLoadedApkField.setAccessible(true);
            Object mloadedApk = mLoadedApkField.get(appContext);
            Class loadedApkClass = Class.forName("android.app.LoadedApk");
            Field mReceiversField = loadedApkClass.getDeclaredField("mReceivers");
            mReceiversField.setAccessible(true);
            ArrayMap receivers = (ArrayMap) mReceiversField.get(mloadedApk);
            for (Object receiverMap : receivers.values()) {
                for (Object receiver : ((ArrayMap) receiverMap).keySet()) {
                    Class clazz = receiver.getClass();
                    if (clazz.getName().contains("ProxyChangeListener")) {
                        Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
                        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
                        onReceiveMethod.invoke(receiver, appContext, intent);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    祝你好运!

    【讨论】:

    • 请注意...这在 Android L 甚至 Lollipop 上都可以正常工作,但它通过更改应用程序范围的代理设置来实现(因为 System.setProperty() 调用),这意味着它影响的不仅仅是您的 WebViews。其他组件(例如 Apache HttpClient 或应用程序中的 3rd 库)也可能开始使用代理。
    【解决方案2】:

    Android L 添加了一个 android.net.ProxyInfo 类用于接收代理 信息而不是 android.net.ProxyProperties 类。

    因此,您的代码的简单补丁可能如下所示:

    - final String CLASS_NAME = "android.net.ProxyProperties";
    + String CLASS_NAME;
    + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
    +   CLASS_NAME = "android.net.ProxyProperties";
    + } else {
    +   CLASS_NAME = "android.net.ProxyInfo";
    + } 
      Class cls = Class.forName(CLASS_NAME);
    

    在此处查看详细信息:

    Start using public API for receiving proxy information

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多