Android 中Java和JavaScript互動入門

來源:互聯網
上載者:User

標籤:

如何?JavaScript 和java 互動

實現Java和js互動十分便捷。通常只需要以下幾步。

  • WebView開啟JavaScript指令碼執行
  • WebView設定供JavaScript調用的互動介面。
  • 用戶端和網頁端編寫調用對方的代碼。

#直接看範例程式碼:

java代碼如下:

 

package com.ccb.javascript;import java.net.URISyntaxException;import android.annotation.SuppressLint;import android.annotation.TargetApi;import android.app.Activity;import android.content.Intent;import android.os.Build;import android.os.Bundle;import android.util.Log;import android.webkit.JavascriptInterface;import android.webkit.WebChromeClient;import android.webkit.WebSettings;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.Toast;@TargetApi(Build.VERSION_CODES.DONUT)public class JavaScriptDemo extends Activity {private static final String LOGTAG = "MainActivity";@SuppressLint("JavascriptInterface")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.javascriptdemo);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() {@Overridepublic 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 {@JavascriptInterfacepublic Intent toastMessage(String message) {Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();Intent intent = null;// Parse intent URI into Intent Objectint flags = 0;boolean isIntentUri = false;if (message.startsWith("intent:")) {isIntentUri = true;flags = Intent.URI_INTENT_SCHEME;} else if (message.startsWith("#Intent;")) {isIntentUri = true;}if (isIntentUri) {try {intent = Intent.parseUri(message, flags);} catch (URISyntaxException e) {e.printStackTrace();}}startActivity(intent);return intent;}@JavascriptInterfacepublic 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<br /><a onClick="window.control.toastMessage(‘#Intent;component=com.ccb.javascript/com.ccb.javascript.MainActivity;end‘)" href="";>調用java中的方法</a></html>

  

 

調用樣本js調用Java

調用格式為window.jsInterfaceName.methodName(parameterValues) 此例中我們使用的是control作為注入介面名稱。

具體調用:

<a onClick="window.control.toastMessage(‘#Intent;component=com.ccb.javascript/com.ccb.javascript.MainActivity;end‘)" href="";>調用java中的方法</a>

(‘#Intent;component=com.ccb.javascript/com.ccb.javascript.MainActivity;end‘)  是傳遞一個開啟Activity的Intent。也可以是字串或者其他。

  

Java調用JS

webView調用js的基本格式為webView.loadUrl(“javascript:methodName(parameterValues)”)

調用js無參無傳回值函數
String call = "javascript:sayHello()";webView.loadUrl(call);

  

調用js有參無傳回值函數

注意對於字串作為參數值需要進行轉義雙引號。

 

String call = "javascript:alertMessage(\"" + "content" + "\")";webView.loadUrl(call);

  

 

調用js有參數有傳回值的函數

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函數傳回值

 

@JavascriptInterfacepublic void onSumResult(int result) {  Log.i(LOGTAG, "onSumResult result=" + result);}

  

 

4.4處理

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也執行在主線程。

  

 

疑問解答Alert無法彈出

你應該是沒有設定WebChromeClient,按照以下代碼設定

 

myWebView.setWebChromeClient(new WebChromeClient() {});

  

Uncaught ReferenceError: functionName is not defined

問題出現原因,網頁的js代碼沒有載入完成,就調用了js方法。解決方案是在網頁載入完成之後調用js方法

 

myWebView.setWebViewClient(new WebViewClient() {  @Override  public void onPageFinished(WebView view, String url) {      super.onPageFinished(view, url);      //在這裡執行你想調用的js函數  }  });

  

Uncaught TypeError: Object [object Object] has no method安全限制問題

如果只在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 code (the method must 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 or higher.

中文大意為

警告:如果你的程式目標平台是17或者是更高,你必須要在暴露給網頁可調用的方法(這個方法必須是公開的)加上@JavascriptInterface注釋。如果你不這樣做的話,在4.2以以後的平台上,網頁無法訪問到你的方法。

解決方案
  • 將targetSdkVersion設定成17或更高,引入@JavascriptInterface注釋
  • 自己建立一個注釋介面名字為@JavascriptInterface,然後將其引入。注意這個介面不能混淆。這種方式不推薦,大概在4.4之後有問題。

注,建立@JavascriptInterface代碼

public @interface JavascriptInterface {}

  

代碼混淆問題

如果在沒有混淆的版本運行正常,在混淆後的版本的代碼運行錯誤,並提示Uncaught TypeError: Object [object Object] has no method,那就是你沒有做混淆例外處理。 在混淆檔案加入類似這樣的代碼

 

keepattributes *Annotation*keepattributes 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)

  

 

在js調用後的Java回調線程並不是主線程。如列印日誌可驗證

 

ThreadInfo=Thread[WebViewCoreThread,5,main]

 

 

解決上述的異常,將webview操作放在主線程中即可。

 

webView.post(new Runnable() {    @Override    public void run() {        webView.loadUrl(YOUR_URL).    }});

  

 轉自:http://droidyue.com/blog/2014/09/20/interaction-between-java-and-javascript-in-android/

Android 中Java和JavaScript互動入門

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.