package nya.miku.wishmaster.lib;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import nya.miku.wishmaster.common.Logger;
import android.content.Context;
/**
* Костыль для установки прокси в WebView (рефлексивный).<br>
* http://stackoverflow.com/questions/4488338/webview-android-proxy<br>
* Изменения:<ul>
* <li>в случае host == null происходит сброс настроек прокси</li>
* <li>экземпляр org.apache.http.HttpHost создаётся рефлексивно</li></ul>
*/
public class WebViewProxy {
private static final String TAG = "WebViewProxy";
/**
* Установить или сбросить HTTP прокси. Устанавливается глобально на весь класс android.webkit.Network,
* так что необходимо не забывать сбрасывать настройки прокси после использования, если они нужны не всегда.
* @param сontext контекст для получения экземпляра android.webkit.Network
* @param host адрес прокси сервера или NULL, если необходимо сбросить настройки
* @param port порт прокси сервера
* @return true, если операция выполнена успешно
*/
public static boolean setProxy(Context сontext, String host, int port) {
Logger.d(TAG, "Setting proxy with <= 3.2 API.");
Object proxyServer = null;
if (host != null) {
try {
proxyServer = Class.forName("org.apache.http.HttpHost").getConstructor(String.class, int.class).newInstance(host, port);
if (proxyServer == null) {
Logger.e(TAG, "failed to create instance of org.apache.http.HttpHost: null returned");
return false;
}
} catch (Exception ex) {
Logger.e(TAG, "failed to create instance of org.apache.http.HttpHost", ex);
return false;
}
}
// Getting network
Class<?> networkClass = null;
Object network = null;
try {
networkClass = Class.forName("android.webkit.Network");
if (networkClass == null) {
Logger.e(TAG, "failed to get class for android.webkit.Network");
return false;
}
Method getInstanceMethod = networkClass.getMethod("getInstance", Context.class);
if (getInstanceMethod == null) {
Logger.e(TAG, "failed to get getInstance method");
}
network = getInstanceMethod.invoke(networkClass, new Object[]{сontext});
} catch (Exception ex) {
Logger.e(TAG, "error getting network", ex);
return false;
}
if (network == null) {
Logger.e(TAG, "error getting network: network is null");
return false;
}
Object requestQueue = null;
try {
Field requestQueueField = networkClass.getDeclaredField("mRequestQueue");
requestQueue = getFieldValueSafely(requestQueueField, network);
} catch (Exception ex) {
Logger.e(TAG, "error getting field value", ex);
return false;
}
if (requestQueue == null) {
Logger.e(TAG, "Request queue is null");
return false;
}
Field proxyHostField = null;
try {
Class<?> requestQueueClass = Class.forName("android.net.http.RequestQueue");
proxyHostField = requestQueueClass.getDeclaredField("mProxyHost");
} catch (Exception ex) {
Logger.e(TAG, "error getting proxy host field", ex);
return false;
}
boolean temp = proxyHostField.isAccessible();
try {
proxyHostField.setAccessible(true);
proxyHostField.set(requestQueue, proxyServer);
} catch (Exception ex) {
Logger.e(TAG, "error setting proxy host", ex);
} finally {
proxyHostField.setAccessible(temp);
}
Logger.d(TAG, "Setting proxy with <= 3.2 API successful!");
return true;
}
private static Object getFieldValueSafely(Field field, Object classInstance) throws IllegalArgumentException, IllegalAccessException {
boolean oldAccessibleValue = field.isAccessible();
field.setAccessible(true);
Object result = field.get(classInstance);
field.setAccessible(oldAccessibleValue);
return result;
}
}