如果你想要載入的頁面中使用了JavaScript,你必須為你的WebView啟用JavaScript。一旦使能之後,你也可以自己建立介面在你的應用程式和JavaScript程式碼間進行互動。
可以透過getSettings()取得WebSettings,然後用setJavaScriptEnabled()使能JavaScript:
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
綁定JavaScript與Android程式碼
#當你為你的Android應用程式中的WebView專門開發一個網頁應用程式時,你可以建立你的JavaScript程式碼和你的客戶端的Android程式碼之間的介面。
例如,你可以用JavaScript程式碼呼叫Android程式碼中的方法,來展現一個對話框之類,而不是使用alert()方法(JS中的對話框方法)。
在JS和Android程式碼間綁定一個新的接口,需要呼叫 addJavascriptInterface()方法。
方法參數傳入一個Java物件實例和一個字串,該字串是一個名字(interface name,注意此接口不是通常所說的那個用來實現的接口,而是傳入的這個物件在JS中的別名),在JS程式碼中用此名字呼叫該Java物件的方法。
注意這個方法可以讓JS程式碼控制宿主程序,這是一個非常強大的特性,但是同時也存在一些安全性問題,因為進一步JS程式碼可以透過反射存取到注入物件的公有域。攻擊者可能會在HTML和JavaScript中包含了有威脅性的程式碼。
所以Android 4.1,API 17,也就是JELLY_BEAN 開始,只有被JavascriptInterface 註解識別的公有方法可以被JS程式碼存取。
另外,因為JS程式碼和Java物件在這個WebView所私有的後台執行緒交互,所以還需要注意線程安全性問題。
注意,與JS程式碼綁定的這個Java物件運行在另一個執行緒中,與創建它的執行緒不是一個執行緒。
注意,這個Java物件的域是無法存取的。
綁定JavaScript與Android程式碼的範例
例如可以定義這麼一個類別:
/** * 自定义的Android代码和JavaScript代码之间的桥梁类 * * @author 1 * */ public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page */ // 如果target 大于等于API 17,则需要加上如下注解 // @JavascriptInterface public void showToast(String toast) { // Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show(); } }
然後將這個類別和你的WebView中的JS程式碼綁定:
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
給這個物件起的別名叫「Android」。
這個就創立了一個介面名,叫做“Android”,運行在WebView中的JS程式碼可以透過這個名字呼叫WebAppInterface類別中的showToast()方法:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
#特別注意:需要設定chrome handler
兩個問題:
1、網頁按鈕按下後不出現JS對話框是因為沒有設定chrome handler,需要設定如下:
// 如果不设置这个,JS代码中的按钮会显示,但是按下去却不弹出对话框 // Sets the chrome handler. This is an implementation of WebChromeClient // for use in handling JavaScript dialogs, favicons, titles, and the // progress. This will replace the current handler. myWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { // TODO Auto-generated method stub return super. onJsAlert(view, url, message, result); } });
2.呼叫Android程式碼的那個按鈕也沒有出現Toast是因為我把別名寫錯了(大小寫沒有註意)。
Android呼叫JavaScript程式碼
這個還比較簡單,需要呼叫的時候只需要一行程式碼:
myWebView.loadUrl("javascript:myFunction()");
其中myFunction()是JS函數。
這裡要補充一下,如果JavaScript函數是帶參數的,那麼呼叫時要特別注意。
例如下面這個JS函數,在原來內容上加入一行:
function writeLine(string) { console.log("Write a new Line"); //调试信息 document.getElementById("content").innerHTML += string + "<br />"; //在content标签段落加入新行 }
註:其中content是自訂的標籤,html中有一個段落是:
<p id="content"></p>
那麼在Android程式碼中呼叫這個writeLine()函數時,就需要傳入一個字串參數,例如,想要傳入一個叫name的String:
myWebView.loadUrl("javascript:writeLine('"+name+"')"); //JS代码要是带参数
還有就是要注意雙引號中的函數名一定不要寫錯。
程式實例
效果如下:
#介面中包含一個TextView,旁邊一個Button,下面整個是一個WebView。
在WebView中載入了一個本機html文件,本地文件存放在assets資料夾中。
網頁中前四個按鈕呼叫的是JavaScript函數,顯示各種對話方塊。
SayHello按鈕呼叫Android程式碼中的一個方法,顯示一個Toast,如圖中所示。
為了證明Android也可以呼叫JS程式碼,最上方的Android Button按下後和「點擊這裡」那個按鈕的效果一致,都是出現JS的對話框。
Activity程式碼:
package com.example.hellowebjs; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.Toast; public class WebJSActivity extends Activity { private WebView myWebView = null; private Button myButton = null; @SuppressLint("SetJavaScriptEnabled") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_web_js); myWebView = (WebView) findViewById(R.id.myWebView); // 得到设置属性的对象 WebSettings webSettings = myWebView.getSettings(); // 使能JavaScript webSettings.setJavaScriptEnabled(true); // 支持中文,否则页面中中文显示乱码 webSettings.setDefaultTextEncodingName("GBK"); // 限制在WebView中打开网页,而不用默认浏览器 myWebView.setWebViewClient(new WebViewClient()); // 如果不设置这个,JS代码中的按钮会显示,但是按下去却不弹出对话框 // Sets the chrome handler. //This is an implementation of WebChromeClient // for use in handling JavaScript dialogs, favicons, //titles, and the // progress. This will replace the current handler. myWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { // TODO Auto-generated method stub return super.onJsAlert(view, url, message, result); } }); // 用JavaScript调用Android函数: // 先建立桥梁类,将要调用的Android代码写入桥梁类的public函数 // 绑定桥梁类和WebView中运行的JavaScript代码 // 将一个对象起一个别名传入,在JS代码中用这个别名代替这个对象, 可以调用这个对象的一些方法 myWebView.addJavascriptInterface(new WebAppInterface(this), "myInterfaceName"); // 载入页面:本地html资源文件 myWebView.loadUrl("file:///android_asset/sample.html"); // 这里用一个Android按钮按下后调用JS中的代码 myButton = (Button) findViewById(R.id.button1); myButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 用Android代码调用JavaScript函数: myWebView.loadUrl("javascript:myFunction()"); // 这里实现的效果和在网页中点击第一个按钮的效果一致 } }); } /** * 自定义的Android代码和JavaScript代码之间的桥梁类 * * @author 1 * */ public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page */ // 如果target 大于等于API 17,则需要加上如下注解 // @JavascriptInterface public void showToast(String toast) { // Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show(); } } }
HTML檔案:
<html> <head> <h1> This is a HTML Page </h1> <!-- JavaScript脚本,主要包括了按钮要执行的函数,显示对话框等 --> <script type="text/javascript"> //JavaScript方法,弹出对话框显示信息 function myFunction() { alert("Hello World!"); } function onAlert() { console.log("onAlert method"); //显示调试信息 alert("This is a alert sample from html"); } function onConfirm() { console.log("onConfirm method"); var b = confirm("are you sure to login?"); alert("your choice is " + b); } function onPrompt() { console.log("onPrompt method"); var b = prompt("please input your password", "aaa"); alert("your input is " + b); } //调用绑定的Java对象的方法,即调用Android代码显示对话框 function showAndroidToast(toast) { console.log("showAndroidToast method"); myInterfaceName.showToast(toast); //注意此处的myInterfaceName要和外部传入的名字一致,大小写正确 } </script> </head> <body> <p> <!-- 前四个按钮调用JS函数 --> JavaScript函数调用 <br /> <button onclick="myFunction()">点击这里!</button> <br /> <input type="button" value="alert" onclick="onAlert()" /> <br /> <input type="button" value="confirm" onclick="onConfirm()" /> <br /> <input type="button" value="prompt" onclick="onPrompt()" /> <br /> <!-- 上面用了两种定义按钮的方式,效果一样的 --> </p> <p> <!-- 这个Say hello 按钮调用Android代码中的方法 --> 用JavaScript按钮调用Android代码 <br /> <input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> </p> <a href="http://www.google.com" />Google </a> </body> </html>
Activity佈局檔案:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/myRelativeLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/padding_medium" android:text="@string/hello_world" tools:context=".WebJSActivity" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/textView1" android:text="@string/btn1_text" /> <WebView android:id="@+id/myWebView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@id/textView1" /> </RelativeLayout>
更多程式設計相關知識,請造訪:程式設計教學! !
以上是在WebView中使用JavaScript的方法介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!