Android WebView代理设置方法(API10~21适用)

  • A+
所属分类:Android开发

最近碰到个需求需要在APP中加入代理,HttpClient的代理好解决,但是WebView碰到些问题,然后找到个API10~API21都通用的类,需要用的同学自己看吧,使用方法,直接调用类方法setProxy即可,applicationName可以设置为null。

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

直接拿来就用。

avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: