代理设置在上次更新Android系统Webview后停止工作
在Android系统Webview的最后一次更新(2018年5月30日)之后,代理设置不再适用于我,代理不再适用于Webview。在其他使用代理的浏览器中,效果相同,未设置代理,阻止的网站未打开,ip未更改。返回的错误为主机不是解析程序或连接失败。 我的设备是Nexus5x,安卓8.1.0。还有其他人面临同样的问题吗 我正在使用此设置代理:代理设置在上次更新Android系统Webview后停止工作,android,webview,proxy,Android,Webview,Proxy,在Android系统Webview的最后一次更新(2018年5月30日)之后,代理设置不再适用于我,代理不再适用于Webview。在其他使用代理的浏览器中,效果相同,未设置代理,阻止的网站未打开,ip未更改。返回的错误为主机不是解析程序或连接失败。 我的设备是Nexus5x,安卓8.1.0。还有其他人面临同样的问题吗 我正在使用此设置代理: private static boolean setProxyKKPlus(WebView webView, String host, int port,
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;
}
此代码在我的环境(Chrome67+Android7.0)中工作
为了扩展@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);
}
}
publicstaticvoidsetproxy(上下文上下文、字符串代理主机、字符串代理端口){
//设置代理值
System.setProperty(“http.proxyHost”,proxyHost);
System.setProperty(“http.proxyPort”,proxyPort);
System.setProperty(“https.proxyHost”,proxyHost);
System.setProperty(“https.proxyPort”,proxyPort);
//使用反射应用新的代理值。
试一试{
//获取应用程序和APK类。抑制lint警告,即反射可能不会在将来和所有设备上始终工作。
Class applicationClass=Class.forName(“android.app.Application”);
@SuppressLint(“PrivateApi”)类LoadedAppClass=Class.forName(“android.app.LoadedAppk”);
//获取声明的字段。取消显示“mLoadedApk”无法解析的lint警告。
@SuppressWarnings(“JavaReflectionMemberAccess”)字段mLoadedApkField=applicationClass.getDeclaredField(“mLoadedApk”);
字段mReceiversField=LoadedAppClass.getDeclaredField(“mReceivers”);
//允许更改值。
mLoadedApkField.setAccessible(true);
mReceiversField.setAccessible(true);
//获取APK对象。
对象mLoadedApkObject=mLoadedApkField.get(上下文);
//获取接收器的阵列图。
ArrayMap receivers=(ArrayMap)mReceiversField.get(mLoadedApkObject);
//设置代理。
对于(对象receiverMap:receivers.values()){
对于(对象接收器:((ArrayMap)receiverMap).keySet()){
//必须使用“类”,它是“无界通配符参数化类型”,而不是“类”,它是“原始类型”。否则,“receiveClass.getDeclaredMethod”不满意。
类receiverClass=receiver.getClass();
//获取声明的字段。
最终字段[]declaredFieldArray=receiverClass.getDeclaredFields();
//为每个“ProxyChangeListener”字段设置代理。
for(字段:declaredFieldArray){
if(field.getType().getName()包含(“ProxyChangeListener”)){
方法onReceiveMethod=ReceiveClass.getDeclaredMethod(“onReceive”,Context.class,Intent.class);
意向意向=新意向(代理、代理、变更、动作);
调用(接收者、上下文、意图);
}
}
}
}
}catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException异常){
Log.d(“enableProxyThroughOrbot”,“异常:”+异常);
}
}
问题出在chromium bug tracker上:
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);
}
}