上次更新Android System Webview后,代理设置停止工作

采得百花成蜜后,为谁辛苦为谁甜。这篇文章主要讲述上次更新Android System Webview后,代理设置停止工作相关的知识,希望能为你提供帮助。
在android System Webview的最后一次更新(2018年5月30日)之后,代理设置停止了为我工作,代理不再适用于webview。在其他具有代理的浏览器中,它具有相同的效果,代理不设置,阻止的网站无法打开,ip不会更改。返回的错误是主机无解析器或连接失败。我的设备是Nexus 5X,Android 8.1.0。其他人是否面临同样的问题?
我用它来设置代理:

private static boolean setProxyKKPlus(WebView webView, String host, int port, String applicationClassName) { Log.d(LOG_TAG, "Setting proxy with > = 4.4 API."); 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(applicationClassName); 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("android.intent.action.PROXY_CHANGE"); onReceiveMethod.invoke(rec, appContext, intent); } } }Log.d(LOG_TAG, "Setting proxy with > = 4.4 API successful!"); return true; } catch (Exception 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 System Webview后,代理设置停止工作】此代码适用于我的环境(Chrome 67 + Android 7.0)
for (Object receiverMap : receivers.values()) { for (Object rec : ((ArrayMap) receiverMap).keySet()) { Class clazz = rec.getClass(); boolean targetReceiverFound = false; if (clazz.getName().contains("ProxyChangeListener")) { targetReceiverFound = true; } else { final Field[] obfuscatedFields = clazz.getDeclaredFields(); for (Field f : obfuscatedFields) { if (f.getType().getName().contains("ProxyChangeListener")) { targetReceiverFound = true; break; } } }if (targetReceiverFound) { // invoke onReceive() here } } }

另一答案为了扩展@Anmerris提供的答案,以下是一个适合我的完整代码集。我使用WebView 30.0.0.0到67.0.3396.87对API 19到27进行了测试。
public static void setProxy(Context context, String proxyHost, String proxyPort) { // Set the proxy values System.setProperty("http.proxyHost", proxyHost); System.setProperty("http.proxyPort", proxyPort); System.setProperty("https.proxyHost", proxyHost); System.setProperty("https.proxyPort", proxyPort); // Use reflection to apply the new proxy values. try { // Get the application and APK classes.Suppress the lint warning that reflection may not always work in the future and on all devices. Class applicationClass = Class.forName("android.app.Application"); @SuppressLint("PrivateApi") Class loadedApkClass = Class.forName("android.app.LoadedApk"); // Get the declared fields.Suppress the lint warning that `mLoadedApk` cannot be resolved. @SuppressWarnings("javaReflectionMemberAccess") Field mLoadedApkField = applicationClass.getDeclaredField("mLoadedApk"); Field mReceiversField = loadedApkClass.getDeclaredField("mReceivers"); // Allow the values to be changed. mLoadedApkField.setAccessible(true); mReceiversField.setAccessible(true); // Get the APK object. Object mLoadedApkObject = mLoadedApkField.get(context); // Get an array map of the receivers. ArrayMap receivers = (ArrayMap) mReceiversField.get(mLoadedApkObject); // Set the proxy. for (Object receiverMap : receivers.values()) { for (Object receiver : ((ArrayMap) receiverMap).keySet()) { // `Class< ?> `, which is an `unbounded wildcard parameterized type`, must be used instead of `Class`, which is a `raw type`.Otherwise, `receiveClass.getDeclaredMethod` is unhappy. Class< ?> receiverClass = receiver.getClass(); // Get the declared fields. final Field[] declaredFieldArray = receiverClass.getDeclaredFields(); // Set the proxy for each field that is a `ProxyChangeListener`. for (Field field : declaredFieldArray) { if (field.getType().getName().contains("ProxyChangeListener")) { Method onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context.class, Intent.class); Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); onReceiveMethod.invoke(receiver, context, intent); } } } } } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException exception) { Log.d("enableProxyThroughOrbot", "Exception: " + exception); } }


    推荐阅读