1. 程式人生 > >Android WebView與JavaScript交互操作(Demo)

Android WebView與JavaScript交互操作(Demo)

-m title manifest ica rri override 事件 能夠 url

版權聲明:本文為博主原創文章,未經博主同意不得轉載。 https://blog.csdn.net/ma_hoking/article/details/32707013

應用場景:

? ? ? ?為了使Android移動項目能夠在較短的時間內完畢開發。同一時候減少技術人員開發的成本投入。往往會採用Hybrid APP的開發模式。相關Hybrid APP(混合型應用)參看:http://blog.csdn.net/mahoking/article/details/30235243 採用這種模式,為了解決更好的用戶體驗。可訪問本地資源的能力。勢必須要了解與掌握Android(java)與JavaScript之間的交互、相互調用操作的方法與技術。

【轉載使用。請註明出處:http://blog.csdn.net/mahoking/article/details/32707013】

知識點介紹:

? ? ? ??本文重要的知識點補充是WebView對象(android.webkit.WebView)。
在Android手機中內置了一款高性能webkit內核瀏覽器。在Android SDK中封裝為一個叫做WebView組件。

?
? ? ? ? WebKit是Mac OS X v10.3及以上版本號所包括的軟件框架(對v10.2.7及以上版本號也可通過軟件更新獲取)。 同一時候。WebKit也是Mac OS X的Safari網頁瀏覽器的基礎。WebKit是一個開源項目。主要由KDE的KHTML改動而來而且包括了一些來自蘋果公司的一些組件。?

? ? ? ? ?傳統上,WebKit包括一個網頁引擎WebCore和一個腳本引擎JavaScriptCore。它們分別相應的是KDE的KHTML和KJS。只是, 隨著JavaScript引擎的獨立性越來越強,如今WebKit和WebCore已經基本上混用不分(比如Google Chrome和Maxthon 3採用V8引擎,卻仍然宣稱自己是WebKit內核)。
【註意事項】
1.AndroidManifest.xml中必須使用許可"android.permission.INTERNET",否則會出Web page not available錯誤。
2.假設訪問的頁面中有Javascript。則webview必須設置支持Javascript。webview.getSettings().setJavaScriptEnabled(true); ?
3.假設頁面中鏈接,假設希望點擊鏈接繼續在當前browser中響應,而不是新開Android的系統browser中響應該鏈接,必須覆蓋 webview的WebViewClient對象。
4.對於第一點, 假設使用Android SDK提供了一個schema,前綴為"file:///android_asset/"。WebView遇到這種schema。會去載入assets文件夾下的資源。

如"file:///android_asset/demo.html"。可不必使用許可"android.permission.INTERNET"。
? ? ? ? 在使用WebView組件的過程中可能會接觸到WebViewClient與WebChromeClient,那麽這兩個類究竟有什麽不同呢?
? ? ? ? ?WebViewClient主要幫助WebView處理各種通知、請求事件的。比方:

  • onLoadResource
  • onPageStart
  • onPageFinish
  • onReceiveError 等
? ? ? ? ? ? ??WebChromeClient主要輔助WebView處理Javascript的對話框、站點圖標、站點title、載入進度等比方:
  • onCloseWindow(關閉WebView)
  • onCreateWindow()
  • onJsAlert (WebView上alert無效,須要定制WebChromeClient處理彈出)
  • onJsPrompt
  • onJsConfirm
  • onReceivedTitle等
? ? ? ? ? ? ?兩者存在非常多的區別。在實際使用過程中,假設你僅僅準備讓WebView處理一些html的頁面內容,僅僅用WebViewClient就能夠了。假設須要產生更豐富的處理效果,比方JS對話框、進度條等,就要使用到WebChromeClient。更進一步的介紹將在以下進行。

【轉載使用,請註明出處:http://blog.csdn.net/mahoking/article/details/32707013】


使用方式:

第一步: 本文的演示程序的主界面為activity_web.xml,相應的Activtiy為WebActivtiy.java。
【activity_web.xml】
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    tools:context=".WebActivity" >
    <LinearLayout android:layout_height="wrap_content" 
        android:background="@drawable/bgcolorblue"
        android:id="@+id/top_layout"
        android:layout_width="match_parent"
        android:layout_alignParentTop="true"
        android:orientation="horizontal">
        <Button android:layout_height="wrap_content"
            android:background="@drawable/titlebackground"
            android:layout_weight="1"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_width="match_parent"
            android:id="@+id/javaCallJs_web_button"
            android:text="Java調用無參數JS"/>
        <Button android:layout_height="wrap_content"
            android:background="@drawable/titlebackground"
            android:layout_weight="1"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_width="match_parent"
            android:id="@+id/javaCallJsParam_web_button"
            android:text="Java調用含參數JS"/>
    </LinearLayout>
    <WebView 
        android:layout_below="@id/top_layout"
        android:id="@+id/webView_web"
        android:layout_width="match_parent"
    	android:layout_height="match_parent"/>
</RelativeLayout>

【WebActivtiy.java】
package cn.mahaochen.webviewtest;

import cn.mahaochen.webviewtest.assist.ButtonListener;
import cn.mahaochen.webviewtest.assist.MJavascriptInterface;
import cn.mahaochen.webviewtest.assist.MWebChromeClient;
import cn.mahaochen.webviewtest.assist.MWebViewClient;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.KeyEvent;
import android.view.Menu;
import android.webkit.WebView;
import android.widget.Button;

/**
 * @date 2014-6-20
 * @author MaHaochen
 */
public class WebActivity extends Activity {
	private WebView webView;
	private Button paramButton;
	private Button noParamButton;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_web);
		initViews();
	}

	private void initViews() {
		webView = (WebView) findViewById(R.id.webView_web);
		// 設置WebView對JavaScript的支持
		webView.getSettings().setJavaScriptEnabled(true);
		// 從assets文件夾以下的載入html
		webView.loadUrl("file:///android_asset/web.html");
		//自己定義WebView的背景顏色
		webView.setBackgroundColor(Color.TRANSPARENT);//先設置背景色為transparent
//		webView.setBackgroundResource(R.drawable.webbg);//然後設置背景圖片
		webView.setBackgroundResource(R.drawable.bgcolorblue);
//		webView.loadUrl("http://www.baidu.com");
		MWebViewClient mWebViewClient = new MWebViewClient(webView,getApplicationContext());
		webView.setWebViewClient(mWebViewClient);
		MWebChromeClient mWebChromeClient = new MWebChromeClient(getApplicationContext());
		webView.setWebChromeClient(mWebChromeClient);
		//加入JS調用Android(Java)的方法接口
		MJavascriptInterface mJavascriptInterface = new MJavascriptInterface(getApplicationContext());
		webView.addJavascriptInterface(mJavascriptInterface, "WebViewFunc");
		
		//初始化按鈕,並綁定監聽事件。事件的作用是調用JS的功能方法
		noParamButton = (Button) findViewById(R.id.javaCallJs_web_button);
		paramButton = (Button) findViewById(R.id.javaCallJsParam_web_button);
		ButtonListener buttonListener = new ButtonListener(webView);
		noParamButton.setOnClickListener(buttonListener);
		paramButton.setOnClickListener(buttonListener);
	}
	
	/**
	 * 退出監聽
	 */
	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
			if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
					&& event.getAction() == KeyEvent.ACTION_DOWN
					&& event.getRepeatCount() == 0
					) {
				if(webView.canGoBack()){
					webView.goBack();
					return false;
				}else {
					WebActivity.this.finish();
					return true;
				}
			}
			return false;
//		return super.dispatchKeyEvent(event);
	}

	//*******************華麗的切割線***********************
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
//		getMenuInflater().inflate(R.menu.web, menu);
		return true;
	}
}

第二步: ? ? ? ? 從第一步能夠看到,以上補充了分別繼承自WebViewClient、WebChromeClient的MWebViewClient、MWebChromeClient對象和MJavascriptInterface、ButtonListener對象。相應的對象的相關方法與操作的介紹將會在代碼中較具體的敘述。
【MWebViewClient.java】
package cn.mahaochen.webviewtest.assist;

import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.util.Log;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

/**
 * @date 2014-6-20
 * @author MaHaochen
 */
public class MWebViewClient  extends WebViewClient {

	private WebView webView;
	private Context context;
	
	public MWebViewClient(WebView webView) {
		super();
		this.webView = webView;
	}

	public MWebViewClient(WebView webView, Context context) {
		super();
		this.webView = webView;
		this.context = context;
	}

	/**
	 * 在點擊請求的是鏈接是才會調用,
	 * 重寫此方法返回true表明點擊網頁裏面的鏈接還是在當前的webview裏跳轉,不跳到瀏覽器那邊。
	 */
	@Override
	public boolean shouldOverrideUrlLoading(WebView view, String url) {
		// 使用自己的WebView組件來響應Url載入事件。而不是使用默認瀏覽器器載入頁面
		webView.loadUrl(url);
		// 記得消耗掉這個事件。

給不知道的朋友再解釋一下。Android中返回True的意思就是到此為止, // 事件就會不會冒泡傳遞了,我們稱之為消耗掉 return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { // Toast.makeText(context, "WebViewClient.onPageStarted頁面開始載入", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "頁面載入開始"); super.onPageStarted(view, url, favicon); } @Override public void onPageFinished(WebView view, String url) { // Toast.makeText(context, "WebViewClient.onPageFinished頁面載入完畢", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "頁面載入完畢"); super.onPageFinished(view, url); } /** * 在載入頁面資源時會調用,每個資源(比方圖片)的載入都會調用一次。 */ @Override public void onLoadResource(WebView view, String url) { // Toast.makeText(context, "WebViewClient.onLoadResource", Toast.LENGTH_SHORT).show(); Log.e("WebActivity", "onLoadResource"); super.onLoadResource(view, url); } /** * 重寫此方法能夠讓webview處理https請求 [拓展] */ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { super.onReceivedSslError(view, handler, error); } }


【MWebChromeClient.java】
package cn.mahaochen.webviewtest.assist;

import android.app.Activity;
import android.content.Context;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

/**
 * @date 2014-6-20
 * @author MaHaochen
 */
public class MWebChromeClient extends WebChromeClient {

	private Context context;
	
	public MWebChromeClient(Context context) {
		super();
		this.context = context;
	}

	// 處理Alert事件
	@Override
	public boolean onJsAlert(WebView view, String url, String message,
			JsResult result) {
		return super.onJsAlert(view, url, message, result);
	}

	// onReceivedTitle()方法改動網頁標題
	@Override
	public void onReceivedTitle(WebView view, String title) {
		((Activity)context).setTitle("能夠用onReceivedTitle()方法改動網頁標題");
		super.onReceivedTitle(view, title);
	}

	// 處理Confirm事件
	@Override
	public boolean onJsConfirm(WebView view, String url, String message,
			JsResult result) {
		return super.onJsConfirm(view, url, message, result);
	}

	// 處理提示事件
	@Override
	public boolean onJsPrompt(WebView view, String url, String message,
			String defaultValue, JsPromptResult result) {
		return super.onJsPrompt(view, url, message, defaultValue, result);
	}
}

【MJavascriptInterface.java】
package cn.mahaochen.webviewtest.assist;

import android.content.Context;
import android.widget.Toast;

/**
 * @date 2014-6-20
 * @author MaHaochen
 */
public class MJavascriptInterface {

	private Context context;

	public MJavascriptInterface(Context context) {
		super();
		this.context = context;
	}
	
	/**
	 * JS調用Android(Java)無參數的方法
	 */
	public void jsCallWebView() {
		Toast.makeText(context, "JS Call Java!",
				Toast.LENGTH_SHORT).show();
	}

	/**
	 * JS調用Android(Java)含參數的方法
	 * @param param
	 */
	public void jsCallWebView(String param) {
		Toast.makeText(context, "JS Call Java!" + param,
				Toast.LENGTH_SHORT).show();
	}
}

【ButtonListener.java】
package cn.mahaochen.webviewtest.assist;

import cn.mahaochen.webviewtest.R;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView;

/**
 * @date 2014-6-20
 * @author MaHaochen
 */
public class ButtonListener implements OnClickListener{
	private WebView webView;
	public ButtonListener(WebView webView) {
		super();
		this.webView = webView;
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.javaCallJs_web_button:
			webView.loadUrl("javascript:javacalljs()"); // 無參數調用
			break;
		case R.id.javaCallJsParam_web_button:
		webView.loadUrl("javascript:javacalljsparam(" + "‘含參數‘"+ ")"); // 無參數調用
			break;
		default:
			break;
		}
	}
}

第三步: ? ? ? ? 以上是所有的Java代碼部分的信息。本例旨為演示WebView(Java)與JS(JavaScript)的互操作。

所以須要補充另兩個資源文件web.html與jump.html頁面。該頁面位於項目的assets文件夾下。


【web.html】

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
<script type="text/javascript">

//Java調用JS代碼無參數
function javacalljs(){
	 document.getElementById("content").innerHTML +=     
         "<br\>java調用了js函數";  
}

//Java調用JS代碼有參數
function javacalljsparam(param){
	 document.getElementById("content").innerHTML +=     
         "<br\>java調用了js函數含參數param"+param;  
}

function testFunc(){

	window.WebViewFunc.jsCallWebView();
}

</script>

<title>測試頁面</title>
</head>
<body>
<a onClick="testFunc()">無參數JS調用java代碼</a><br/> 
<a onClick="window.WebViewFunc.jsCallWebView(‘含有參數‘)">含參數調用java代碼</a><br/> 
<br />
<div id="content">內容顯示 <a href="jump.html" target="_self">跳轉新頁面jump.html</a></div>  
</body>
</html>

【jump.html】
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
<script type="text/javascript">

//Java調用JS代碼無參數
function javacalljs(){
	 document.getElementById("content").innerHTML +=     
         "<br\>java調用了js函數";  
}

//Java調用JS代碼有參數
function javacalljsparam(param){
	 document.getElementById("content").innerHTML +=     
         "<br\>java調用了js函數含參數param"+param;  
}

function testFunc(){

	window.WebViewFunc.jsCallWebView();
}

</script>

<title>測試頁面</title>
</head>
<body>
<a onClick="testFunc()">無參數JS調用java代碼</a><br/> 
<a onClick="window.WebViewFunc.jsCallWebView(‘含有參數‘)">含參數調用java代碼</a><br/> 
<br />
<div id="content">內容顯示</div>  
</body>
</html>

■註:因為本演示案例加入必要的圖片文件與樣式文件。才幹夠出現以下效果截圖,所以假設獲取完整的效果,請在【下載地址】欄。自行下載完整項目。


【轉載使用,請註明出處:http://blog.csdn.net/mahoking/article/details/32707013】

效果截圖:

技術分享圖片

下載地址:

http://download.csdn.net/detail/ma_hoking/7525549? ?點擊下載

參考文獻:

1、 http://www.cnblogs.com/oakpip/archive/2011/04/08/2009800.html
2、 http://blog.csdn.net/jackyhuangch/article/details/8310033

Android WebView與JavaScript交互操作(Demo)