Android提供了一個很強大的WebView控制項用來處理Web網頁,而在網頁中,JavaScript又是一個很舉足輕重的腳本。本文將介紹如何實作Java程式碼和Javascript程式碼的相互呼叫。
實作Java和js互動十分便捷。通常只需要以下幾個步驟。
WebView開啟JavaScript腳本執行
WebView設定供JavaScript呼叫的互動介面。
客戶端和網頁端編寫呼叫對方的程式碼。
為了方便講解,先貼出全部程式碼
Java程式碼
package com.example.javajsinteractiondemo; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; public class MainActivity extends Activity { private static final String LOGTAG = "MainActivity"; @SuppressLint("JavascriptInterface") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final WebView myWebView = (WebView) findViewById(R.id.myWebView); WebSettings settings = myWebView.getSettings(); settings.setJavaScriptEnabled(true); myWebView.addJavascriptInterface(new JsInteration(), "control"); myWebView.setWebChromeClient(new WebChromeClient() {}); myWebView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); testMethod(myWebView); } }); myWebView.loadUrl("file:///android_asset/js_java_interaction.html"); } private void testMethod(WebView webView) { String call = "javascript:sayHello()"; call = "javascript:alertMessage(\"" + "content" + "\")"; call = "javascript:toastMessage(\"" + "content" + "\")"; call = "javascript:sumToJava(1,2)"; webView.loadUrl(call); } public class JsInteration { @JavascriptInterface public void toastMessage(String message) { Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); } @JavascriptInterface public void onSumResult(int result) { Log.i(LOGTAG, "onSumResult result=" + result); } } }
前端網頁程式碼
<html> <script type="text/javascript"> function sayHello() { alert("Hello") } function alertMessage(message) { alert(message) } function toastMessage(message) { window.control.toastMessage(message) } function sumToJava(number1, number2){ window.control.onSumResult(number1 + number2) } </script> Java-Javascript Interaction In Android </html>
呼叫格式為window.jsInterfaceName.methodName(parameterValues) 此範例中我們使用的是control作為注入介面名稱。
function toastMessage(message) { window.control.toastMessage(message) } function sumToJava(number1, number2){ window.control.onSumResult(number1 + number2) }
webView呼叫js的基本格式為webView.loadUrl(“javascript:methodName(parameterValues)”)
String call = "javascript:sayHello()"; webView.loadUrl(call);
注意對於字串作為參數值需要進行轉義雙引號。
String call = "javascript:alertMessage(\"" + "content" + "\")"; webView.loadUrl(call);
Android在4.4之前並沒有提供直接呼叫js函數並取得值的方法,所以在此之前,常用的想法是java調用js方法,js方法執行完畢,再次呼叫java程式碼將值回傳。
1.Java呼叫js程式碼
String call = "javascript:sumToJava(1,2)"; webView.loadUrl(call);
2.js函數處理,並將結果透過呼叫java方法傳回
function sumToJava(number1, number2){ window.control.onSumResult(number1 + number2) }
3.Java在回呼方法中取得js函數傳回值
@JavascriptInterface public void onSumResult(int result) { Log.i(LOGTAG, "onSumResult result=" + result); }
Android 4.4之後使用evaluateJavascript即可。這裡展示一個簡單的互動範例具有傳回值的js方法
function getGreetings() { return 1; }
java程式碼時用evaluateJavascript方法呼叫
private void testEvaluateJavascript(WebView webView) { webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { Log.i(LOGTAG, "onReceiveValue value=" + value); }}); }
輸出結果
I/MainActivity( 1432): onReceiveValue value=1
注意
#上面限定了結果返回結果為String,對於簡單的類型會嘗試轉換成字串返回,對於複雜的資料類型,建議以字串形式的json返回。
evaluateJavascript方法必須在UI執行緒(主執行緒)調用,因此onReceiveValue也執行在主執行緒。
你應該是沒有設定WebChromeClient,依照以下程式碼設定
myWebView.setWebChromeClient(new WebChromeClient() {});
問題出現原因,網頁的js程式碼沒有載入完成,就呼叫了js方法。解決方法是在網頁載入完成之後呼叫js方法
myWebView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); //在这里执行你想调用的js函数 } });
如果只在4.2版本以上的機器出問題,那就是系統處於安全限制的問題了。 Android文件這樣說的
Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available your web page codethe method also be public). If you do not provide the annotation, then the method will not accessible by your web page when running on Android 4.2 或 higher.
f ##警告:如果你的程式目標平台是17或更高,你必須在暴露給網頁可呼叫的方法(這個方法必須是公開的)加上@JavascriptInterface
註解。如果你不這麼做的話,在4.2以以後的平台上,網頁無法存取你的方法。#將targetSdkVersion設定為17或更高,引入@JavascriptInterface註解
public @interface JavascriptInterface { }
-keep class com.example.javajsinteractiondemo$JsInteration { *; }
All WebView methods must be called on the same thread
E/StrictMode( 1546): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {528712d4} called on Looper (JavaBridge, tid 121) {52b6678c}, FYI main Looper is Looper (main, tid 1) {528712d4}) E/StrictMode( 1546): at android.webkit.WebView.checkThread(WebView.java:2063) E/StrictMode( 1546): at android.webkit.WebView.loadUrl(WebView.java:794) E/StrictMode( 1546): at com.xxx.xxxx.xxxx.xxxx.xxxxxxx$JavaScriptInterface.onCanGoBackResult(xxxx.java:96) E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method) E/StrictMode( 1546): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27) E/StrictMode( 1546): at android.os.Handler.dispatchMessage(Handler.java:102) E/StrictMode( 1546): at android.os.Looper.loop(Looper.java:136) E/StrictMode( 1546): at android.os.HandlerThread.run(HandlerThread.java:61)
ThreadInfo=Thread[WebViewCoreThread,5,main]
webView.post(new Runnable() { @Override public void run() { webView.loadUrl(YOUR_URL). } });
以上是Android中Java和JavaScript互動的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!