1. 程式人生 > >Android WebView 加載超長 JS 數據

Android WebView 加載超長 JS 數據

int strong catch [] size set native logs 業務

在之前的文章裏面,我總結過WebView如何與網頁交互,也就是Java如何和JS交互 —— Android WebView 總結 —— Java和JavaScript交互。 基於這篇文章,我們基本上能完成絕大部分交互的邏輯。但是,因為業務需要,最近加載的JS都是超長的數據,但測試發現在Android 16及以下的手機上,能正常使用,但是在17 及以上的手機上,發現JS沒有執行。

這是因為,WebView在Android 17及以後對之前的WebView存在的安全問題做了調整。那怎麽辦呢?答:使用 evaluateJavaScript 方法。

這個方法不僅能執行JS,還可以獲取到返回數據,下面是針對這個方法的原文說明:

Asynchronously evaluates JavaScript in the context of the currently displayed page. If non-null, |resultCallback| will be invoked with any result returned from that execution. This method must be called on the UI thread and the callback will be made on the UI thread.
 
Parameters
script    the JavaScript to execute.
resultCallback    A callback to be invoked when the script execution completes with the result of the execution (if any). May be null if no notificaion of the result is required.

那麽Android 17之前的該怎麽辦?目前的解決方案是通過java反射機制!

在android.webkit包中有個BrowserFrame私有類,該類中有個Native方法:

public native String stringByEvaluatingJavaScriptFromString(String script)

使用步驟

1.擴展WebView添加方法,並使用反射實現。

2.將布局文件中的WebView修改為自定義的WebView

3.使用新的WebView調用方法,執行js方法獲取返回值

實現後的自定義WebView調用方法代碼如下:

public String stringByEvaluatingJavaScriptFromString(String script) {
       
try { //由webview取到webviewcore Field field_webviewcore = WebView.class.getDeclaredField("mWebViewCore"); field_webviewcore.setAccessible(true); Object obj_webviewcore = field_webviewcore.get(this); //由webviewcore取到BrowserFrame Field field_BrowserFrame = obj_webviewcore.getClass().getDeclaredField("mBrowserFrame"); field_BrowserFrame.setAccessible(true); Object obj_frame = field_BrowserFrame.get(obj_webviewcore); //獲取BrowserFrame對象的stringByEvaluatingJavaScriptFromString方法 Method method_stringByEvaluatingJavaScriptFromString = obj_frame.getClass().getMethod("stringByEvaluatingJavaScriptFromString", String.class); //執行stringByEvaluatingJavaScriptFromString方法 Object obj_value = method_stringByEvaluatingJavaScriptFromString.invoke(obj_frame, script); //返回執行結果 return String.valueOf(obj_value); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }

當然,還有更簡單的方法,那就是使用騰訊X5內核的WebView提供的evaluateJavaScript,在他們的WebView裏面,針對這個問題已經做好的處理。下面是他們的SDK裏面的相關代碼,在這裏做一下展示:

public void evaluateJavascript(String var1, ValueCallback<String> var2) {
        if (this.e) {
            try {
                View var3 = this.f.getView();
                Method var4 = com.tencent.smtt.utils.q.a(var3, "evaluateJavascript", new Class[]{String.class, android.webkit.ValueCallback.class});
                var4.setAccessible(true);
                var4.invoke(this.f.getView(), var1, var2);
            } catch (Exception var7) {
                var7.printStackTrace();
                this.loadUrl(var1);
            }
        } else if (VERSION.SDK_INT >= 19) {
            try {
                Class var8 = Class.forName("android.webkit.WebView");
                Class[] var9 = new Class[]{String.class, android.webkit.ValueCallback.class};
                Method var5 = var8.getDeclaredMethod("evaluateJavascript", var9);
                var5.setAccessible(true);
                var5.invoke(this.g, var1, var2);
            } catch (Exception var6) {
                var6.printStackTrace();
            }
        }

    }

Android WebView 加載超長 JS 數據