最近碰到个需求需要在APP中加入代理,HttpClient的代理好解决,但是WebView碰到些问题,然后找到个API10~API21都通用的类,需要用的同学自己看吧,使用方法,直接调用类方法setProxy即可,applicationName可以设置为null。
1 /** 2 * Created by shengdong.huang on 2015/9/18. 3 */ 4 public class ProxySettings { 5 6 private static final String LOG_TAG = "halfman"; 7 8 private static final String APPLICATION_NAME = "android.app.Application"; 9 10 11 public static boolean setProxy(WebView webview, String host, int port, String applicationName) { 12 13 14 // 3.2 (HC) or lower 15 if (Build.VERSION.SDK_INT <= 13) { 16 return setProxyUpToHC(webview, host, port); 17 } 18 // ICS: 4.0 19 else if (Build.VERSION.SDK_INT <= 15) { 20 return setProxyICS(webview, host, port); 21 } 22 // 4.1-4.3 (JB) 23 else if (Build.VERSION.SDK_INT <= 18) { 24 return setProxyJB(webview, host, port); 25 } 26 // 4.4 (KK) & 5.0 (Lollipop) 27 else { 28 return setProxyKKPlus(webview, host, port, 29 applicationName == null ? APPLICATION_NAME : applicationName); 30 } 31 } 32 33 /** 34 * Set Proxy for Android 3.2 and below. 35 */ 36 @SuppressWarnings("all") 37 private static boolean setProxyUpToHC(WebView webview, String host, int port) { 38 Log.d(LOG_TAG, "Setting proxy with <= 3.2 API."); 39 40 HttpHost proxyServer = new HttpHost(host, port); 41 // Getting network 42 Class networkClass = null; 43 Object network = null; 44 try { 45 networkClass = Class.forName("android.webkit.Network"); 46 if (networkClass == null) { 47 Log.e(LOG_TAG, "failed to get class for android.webkit.Network"); 48 return false; 49 } 50 Method getInstanceMethod = networkClass.getMethod("getInstance", Context.class); 51 if (getInstanceMethod == null) { 52 Log.e(LOG_TAG, "failed to get getInstance method"); 53 } 54 network = getInstanceMethod.invoke(networkClass, new Object[]{webview.getContext()}); 55 } catch (Exception ex) { 56 Log.e(LOG_TAG, "error getting network: " + ex); 57 return false; 58 } 59 if (network == null) { 60 Log.e(LOG_TAG, "error getting network: network is null"); 61 return false; 62 } 63 Object requestQueue = null; 64 try { 65 Field requestQueueField = networkClass 66 .getDeclaredField("mRequestQueue"); 67 requestQueue = getFieldValueSafely(requestQueueField, network); 68 } catch (Exception ex) { 69 Log.e(LOG_TAG, "error getting field value"); 70 return false; 71 } 72 if (requestQueue == null) { 73 Log.e(LOG_TAG, "Request queue is null"); 74 return false; 75 } 76 Field proxyHostField = null; 77 try { 78 Class requestQueueClass = Class.forName("android.net.http.RequestQueue"); 79 proxyHostField = requestQueueClass 80 .getDeclaredField("mProxyHost"); 81 } catch (Exception ex) { 82 Log.e(LOG_TAG, "error getting proxy host field"); 83 return false; 84 } 85 86 boolean temp = proxyHostField.isAccessible(); 87 try { 88 proxyHostField.setAccessible(true); 89 proxyHostField.set(requestQueue, proxyServer); 90 } catch (Exception ex) { 91 Log.e(LOG_TAG, "error setting proxy host"); 92 } finally { 93 proxyHostField.setAccessible(temp); 94 } 95 96 Log.d(LOG_TAG, "Setting proxy with <= 3.2 API successful!"); 97 return true; 98 } 99 100 @SuppressWarnings("all") 101 private static boolean setProxyICS(WebView webview, String host, int port) { 102 try 103 { 104 Log.d(LOG_TAG, "Setting proxy with 4.0 API."); 105 106 Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge"); 107 Class params[] = new Class[1]; 108 params[0] = Class.forName("android.net.ProxyProperties"); 109 Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params); 110 111 Class wv = Class.forName("android.webkit.WebView"); 112 Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore"); 113 Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webview); 114 115 Class wvc = Class.forName("android.webkit.WebViewCore"); 116 Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame"); 117 Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance); 118 119 Class bf = Class.forName("android.webkit.BrowserFrame"); 120 Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge"); 121 Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame); 122 123 Class ppclass = Class.forName("android.net.ProxyProperties"); 124 Class pparams[] = new Class[3]; 125 pparams[0] = String.class; 126 pparams[1] = int.class; 127 pparams[2] = String.class; 128 Constructor ppcont = ppclass.getConstructor(pparams); 129 130 updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null)); 131 132 Log.d(LOG_TAG, "Setting proxy with 4.0 API successful!"); 133 return true; 134 } 135 catch (Exception ex) 136 { 137 Log.e(LOG_TAG, "failed to set HTTP proxy: " + ex); 138 return false; 139 } 140 } 141 142 /** 143 * Set Proxy for Android 4.1 - 4.3. 144 */ 145 @SuppressWarnings("all") 146 private static boolean setProxyJB(WebView webview, String host, int port) { 147 Log.d(LOG_TAG, "Setting proxy with 4.1 - 4.3 API."); 148 149 try { 150 Class wvcClass = Class.forName("android.webkit.WebViewClassic"); 151 Class wvParams[] = new Class[1]; 152 wvParams[0] = Class.forName("android.webkit.WebView"); 153 Method fromWebView = wvcClass.getDeclaredMethod("fromWebView", wvParams); 154 Object webViewClassic = fromWebView.invoke(null, webview); 155 156 Class wv = Class.forName("android.webkit.WebViewClassic"); 157 Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore"); 158 Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webViewClassic); 159 160 Class wvc = Class.forName("android.webkit.WebViewCore"); 161 Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame"); 162 Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance); 163 164 Class bf = Class.forName("android.webkit.BrowserFrame"); 165 Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge"); 166 Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame); 167 168 Class ppclass = Class.forName("android.net.ProxyProperties"); 169 Class pparams[] = new Class[3]; 170 pparams[0] = String.class; 171 pparams[1] = int.class; 172 pparams[2] = String.class; 173 Constructor ppcont = ppclass.getConstructor(pparams); 174 175 Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge"); 176 Class params[] = new Class[1]; 177 params[0] = Class.forName("android.net.ProxyProperties"); 178 Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params); 179 180 updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null)); 181 } catch (Exception ex) { 182 Log.e(LOG_TAG,"Setting proxy with >= 4.1 API failed with error: " + ex.getMessage()); 183 return false; 184 } 185 186 Log.d(LOG_TAG, "Setting proxy with 4.1 - 4.3 API successful!"); 187 return true; 188 } 189 190 @SuppressWarnings("all") 191 private static boolean setProxyKKPlus(WebView webView, String host, int port, String applicationClassName) { 192 Log.d(LOG_TAG, "Setting proxy with >= 4.4 API."); 193 194 Context appContext = webView.getContext().getApplicationContext(); 195 System.setProperty("http.proxyHost", host); 196 System.setProperty("http.proxyPort", port + ""); 197 System.setProperty("https.proxyHost", host); 198 System.setProperty("https.proxyPort", port + ""); 199 try { 200 Class applictionCls = Class.forName(applicationClassName); 201 Field loadedApkField = applictionCls.getField("mLoadedApk"); 202 loadedApkField.setAccessible(true); 203 Object loadedApk = loadedApkField.get(appContext); 204 Class loadedApkCls = Class.forName("android.app.LoadedApk"); 205 Field receiversField = loadedApkCls.getDeclaredField("mReceivers"); 206 receiversField.setAccessible(true); 207 ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk); 208 for (Object receiverMap : receivers.values()) { 209 for (Object rec : ((ArrayMap) receiverMap).keySet()) { 210 Class clazz = rec.getClass(); 211 if (clazz.getName().contains("ProxyChangeListener")) { 212 Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class); 213 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); 214 215 onReceiveMethod.invoke(rec, appContext, intent); 216 } 217 } 218 } 219 220 Log.d(LOG_TAG, "Setting proxy with >= 4.4 API successful!"); 221 return true; 222 } catch (ClassNotFoundException e) { 223 StringWriter sw = new StringWriter(); 224 e.printStackTrace(new PrintWriter(sw)); 225 String exceptionAsString = sw.toString(); 226 Log.v(LOG_TAG, e.getMessage()); 227 Log.v(LOG_TAG, exceptionAsString); 228 } catch (NoSuchFieldException e) { 229 StringWriter sw = new StringWriter(); 230 e.printStackTrace(new PrintWriter(sw)); 231 String exceptionAsString = sw.toString(); 232 Log.v(LOG_TAG, e.getMessage()); 233 Log.v(LOG_TAG, exceptionAsString); 234 } catch (IllegalAccessException e) { 235 StringWriter sw = new StringWriter(); 236 e.printStackTrace(new PrintWriter(sw)); 237 String exceptionAsString = sw.toString(); 238 Log.v(LOG_TAG, e.getMessage()); 239 Log.v(LOG_TAG, exceptionAsString); 240 } catch (IllegalArgumentException e) { 241 StringWriter sw = new StringWriter(); 242 e.printStackTrace(new PrintWriter(sw)); 243 String exceptionAsString = sw.toString(); 244 Log.v(LOG_TAG, e.getMessage()); 245 Log.v(LOG_TAG, exceptionAsString); 246 } catch (NoSuchMethodException e) { 247 StringWriter sw = new StringWriter(); 248 e.printStackTrace(new PrintWriter(sw)); 249 String exceptionAsString = sw.toString(); 250 Log.v(LOG_TAG, e.getMessage()); 251 Log.v(LOG_TAG, exceptionAsString); 252 } catch (InvocationTargetException e) { 253 StringWriter sw = new StringWriter(); 254 e.printStackTrace(new PrintWriter(sw)); 255 String exceptionAsString = sw.toString(); 256 Log.v(LOG_TAG, e.getMessage()); 257 Log.v(LOG_TAG, exceptionAsString); 258 } 259 return false; 260 } 261 262 private static Object getFieldValueSafely(Field field, Object classInstance) throws IllegalArgumentException, IllegalAccessException { 263 boolean oldAccessibleValue = field.isAccessible(); 264 field.setAccessible(true); 265 Object result = field.get(classInstance); 266 field.setAccessible(oldAccessibleValue); 267 return result; 268 } 269 }
就是这些,祝码运昌隆~~
时间: 2024-11-10 17:06:41