1
+ import android.annotation.TargetApi;
2
+ import android.content.Context;
3
+ import android.content.Intent;
4
+ import android.net.Proxy;
5
+ import android.os.Build;
6
+ import android.os.Parcelable;
7
+ import android.util.ArrayMap;
8
+ //import org.apache.http.HttpHost;
9
+
10
+ import java.lang.reflect.Constructor;
11
+ import java.lang.reflect.Field;
12
+ import java.lang.reflect.InvocationTargetException;
13
+ import java.lang.reflect.Method;
14
+
15
+ /**
16
+ * Utility class for setting WebKit proxy used by Android WebView
17
+ */
18
+ @SuppressWarnings({"unchecked", "ConstantConditions"})
19
+ public class ProxySettings {
20
+
21
+ private static final String TAG = "ProxySettings";
22
+ public static final String LOG_TAG = TAG;
23
+
24
+ static final int PROXY_CHANGED = 193;
25
+
26
+ private static Object getDeclaredField(Object obj, String name) throws
27
+ SecurityException, NoSuchFieldException,
28
+ IllegalArgumentException, IllegalAccessException {
29
+ Field f = obj.getClass().getDeclaredField(name);
30
+ f.setAccessible(true);
31
+ // System.out.println(obj.getClass().getName() + "." + name + " = "+
32
+ // out);
33
+ return f.get(obj);
34
+ }
35
+
36
+ public static Object getRequestQueue(Context ctx) throws Exception {
37
+ Object ret = null;
38
+ Class networkClass = Class.forName("android.webkit.Network");
39
+ if (networkClass != null) {
40
+ Object networkObj = invokeMethod(networkClass, "getInstance", new Object[]{ctx},
41
+ Context.class);
42
+ if (networkObj != null) {
43
+ ret = getDeclaredField(networkObj, "mRequestQueue");
44
+ }
45
+ }
46
+ return ret;
47
+ }
48
+
49
+ private static Object invokeMethod(Object object, String methodName, Object[] params,
50
+ Class... types) throws Exception {
51
+ Object out = null;
52
+ Class c = object instanceof Class ? (Class) object : object.getClass();
53
+ if (types != null) {
54
+ Method method = c.getMethod(methodName, types);
55
+ out = method.invoke(object, params);
56
+ } else {
57
+ Method method = c.getMethod(methodName);
58
+ out = method.invoke(object);
59
+ }
60
+ // System.out.println(object.getClass().getName() + "." + methodName +
61
+ // "() = "+ out);
62
+ return out;
63
+ }
64
+
65
+ public static void resetProxy(Context ctx) throws Exception {
66
+ Object requestQueueObject = getRequestQueue(ctx);
67
+ if (requestQueueObject != null) {
68
+ setDeclaredField(requestQueueObject, "mProxyHost", null);
69
+ }
70
+ }
71
+
72
+ private static void setDeclaredField(Object obj, String name, Object value)
73
+ throws SecurityException, NoSuchFieldException, IllegalArgumentException,
74
+ IllegalAccessException {
75
+ Field f = obj.getClass().getDeclaredField(name);
76
+ f.setAccessible(true);
77
+ f.set(obj, value);
78
+ }
79
+
80
+ /**
81
+ * Override WebKit Proxy settings
82
+ *
83
+ * @param ctx Android ApplicationContext
84
+ * @param host
85
+ * @param port
86
+ * @return true if Proxy was successfully set
87
+ */
88
+ public static boolean setProxy(Context ctx, String host, int port) {
89
+ boolean ret = false;
90
+ setSystemProperties(host, port);
91
+
92
+ try {
93
+ if (Build.VERSION.SDK_INT > 18) {
94
+ ret = setKitKatProxy(ctx, host, port);
95
+ } else if (Build.VERSION.SDK_INT > 13) {
96
+ ret = setICSProxy(host, port);
97
+ } else {
98
+ /*
99
+ Object requestQueueObject = getRequestQueue(ctx);
100
+ if (requestQueueObject != null) {
101
+ // Create Proxy config object and set it into request Q
102
+ HttpHost httpHost = new HttpHost(host, port, "http");
103
+
104
+ setDeclaredField(requestQueueObject, "mProxyHost", httpHost);
105
+ ret = true;
106
+ */
107
+ return false;
108
+ }
109
+ }
110
+ catch (Exception e) {
111
+ e.printStackTrace();
112
+ }
113
+ return ret;
114
+ }
115
+
116
+ private static boolean setICSProxy(String host, int port) throws
117
+ ClassNotFoundException, NoSuchMethodException,
118
+ IllegalArgumentException, InstantiationException,
119
+ IllegalAccessException, InvocationTargetException {
120
+ Class webViewCoreClass = Class.forName("android.webkit.WebViewCore");
121
+ Class proxyPropertiesClass = Class.forName("android.net.ProxyProperties");
122
+ if (webViewCoreClass != null && proxyPropertiesClass != null) {
123
+ Method m = webViewCoreClass.getDeclaredMethod("sendStaticMessage", Integer.TYPE,
124
+ Object.class);
125
+ Constructor c = proxyPropertiesClass.getConstructor(String.class, Integer.TYPE,
126
+ String.class);
127
+ m.setAccessible(true);
128
+ c.setAccessible(true);
129
+ Object properties = c.newInstance(host, port, null);
130
+ m.invoke(null, PROXY_CHANGED, properties);
131
+ return true;
132
+ }
133
+ return false;
134
+
135
+ }
136
+
137
+ @TargetApi(Build.VERSION_CODES.KITKAT)
138
+ private static boolean setKitKatProxy(Context context, String host, int port) {
139
+ Context appContext = context.getApplicationContext();
140
+ try {
141
+ Class applictionCls = appContext.getClass();
142
+ Field loadedApkField = applictionCls.getField("mLoadedApk");
143
+ loadedApkField.setAccessible(true);
144
+ Object loadedApk = loadedApkField.get(appContext);
145
+ Class loadedApkCls = Class.forName("android.app.LoadedApk");
146
+ Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
147
+ receiversField.setAccessible(true);
148
+ ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
149
+ for (Object receiverMap : receivers.values()) {
150
+ for (Object rec : ((ArrayMap) receiverMap).keySet()) {
151
+ Class clazz = rec.getClass();
152
+ if (clazz.getName().contains("ProxyChangeListener")) {
153
+ Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
154
+ Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
155
+
156
+ /*********** optional, may be need in future ************* /
157
+ final String CLASS_NAME = "android.net.ProxyProperties";
158
+ Class cls = Class.forName(CLASS_NAME);
159
+ Constructor constructor = cls.getConstructor(String.class, Integer.TYPE, String.class);
160
+ constructor.setAccessible(true);
161
+ Object proxyProperties = constructor.newInstance(host, port, null);
162
+ intent.putExtra("proxy", (Parcelable) proxyProperties);
163
+ //*********** optional, may be need in future *************/
164
+
165
+ onReceiveMethod.invoke(rec, appContext, intent);
166
+ }
167
+ }
168
+ }
169
+ return true;
170
+ } catch (Exception e) {
171
+ e.printStackTrace();
172
+ }
173
+ return false;
174
+ }
175
+
176
+ private static void setSystemProperties(String host, int port) {
177
+
178
+ java.lang.System.setProperty("http.proxyHost", host);
179
+ java.lang.System.setProperty("http.proxyPort", port + "");
180
+
181
+ java.lang.System.setProperty("https.proxyHost", host);
182
+ java.lang.System.setProperty("https.proxyPort", port + "");
183
+
184
+ }
185
+ }
0 commit comments