相信大家看完代碼就會明白:
MainActivity.java
package com.example.testjs;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.example.testjs.utils.Constant;
/**
* 實作Android本地Java與JS的互調
* 1.Android調用JS:
* mWebView.loadUrl("javascript:" + "function()");
*
* 2.JS調用Android:
* a.設定WebView支援JS:mWebView.getSettings().setJavaScriptEnabled(true);
* b.建立一個JS調用代理類:class JavascriptInterfaceProxy
* 1).Android 4.2 以後需要将代理類中的方法注解:@JavascriptInterface
* c.mWebView.addJavascriptInterface(new JavascriptInterfaceProxy(), "MyJsInterface");
*
* @author Yanbao_Wu
*
*/
public class MainActivity extends Activity {
public static final String TAG = MainActivity.class.getSimpleName();
public static final int SAY_HELLO = 0;
public static final int SAY_BYEBYE = 1;
private WebView mWebView = null;
@SuppressLint("HandlerLeak")
public Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SAY_HELLO:
Toast.makeText(MainActivity.this, "just say hello from JS", Toast.LENGTH_SHORT).show();
break;
case SAY_BYEBYE:
Toast.makeText(MainActivity.this, "Bye-bye called from JS", Toast.LENGTH_SHORT).show();
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findId();
initWebView(mWebView);
}
/**
* @author Yanbao_Wu
*/
public void findId(){
mWebView = (WebView) findViewById(R.id.webview_contend);
}
/**
* Init the web settings.
*
* @author Yanbao_Wu
*/
@SuppressLint("SetJavaScriptEnabled")
public void initWebView(WebView mWebView){
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
// 設定可以使用localStorage
mWebView.getSettings().setDomStorageEnabled(true);
// 應用可以有資料庫
mWebView.getSettings().setDatabaseEnabled(true);
String cacheDirPath = getFilesDir().getAbsolutePath() + Constant.APP_H5_CACHE_DIRNAME;
// 設定 H5緩存目錄
mWebView.getSettings().setAppCachePath(cacheDirPath);
// 應用可以有緩存
mWebView.getSettings().setAppCacheEnabled(true);
/**
* 注意:
* 由于4.4之前使用的是WebKit核心,而4.4使用的是chromium核心,
* 是以WebViewClient中的方法調用的次數和順序會不一樣,如果按照正常的邏輯處理,
* 可能會出現一些問題,這裡可以做些版本相容性判斷。
*/
mWebView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// 自定義加載過程中的動畫,例如一個loading的界面
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
// 可以自定義錯誤頁面覆寫WebView
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
/*
* 可以擷取Web頁面的Title來設定移動端的Title,
* 但是在部分手機上,調用goBack()方法時,不會觸發onReceivedTitle()方法是以onTitle沒有變化,
* 是以需要做簡單的處理:
* 1.已知WebView最多隻有二級頁面,不存在更深層次的頁面時,可以在調用goBack的時候,直接将Title設定回去就可以了
* 2.當WebView的頁面層次不确定時,可能會有很深層次的頁面,這時需要我們手動的去維護對應頁面的Title的一個棧了,我們可以
* 使用HashMap去維護這樣的(url,title)的棧,當進去新的頁面時直接加到Map中即可,當回退是進行退棧操作就可以了
* 當WebView加載出錯時,Title會顯示"找不到該網頁",是以需要我們在onReceivedError方法中自行更改Title
*/
super.onReceivedTitle(view, title);
}
});
/*
* 第一個參數代理類的對象,第二個參數供JS調用方法的對象名稱
* JS調用的方式大緻可以通過:
* MyJsInterface.testJS();
* MyJsInterface.testLowVerssion(); // Android 4.2以後不能調用
*/
mWebView.addJavascriptInterface(new JavascriptInterfaceProxy(), "MyJsInterface");
mWebView.loadUrl("file:///android_asset/js.html");
}
/**
* The proxy class which used by JS.
*
* @author Yanbao_Wu
*/
public class JavascriptInterfaceProxy{
@JavascriptInterface
public void testJS(){
mHandler.sendEmptyMessage(SAY_HELLO);
mWebView.loadUrl("javascript:wave()");
}
// 4.2以後不能被JS調用
public void testLowVerssion(){
mHandler.sendEmptyMessage(SAY_BYEBYE);
}
}
@Override
protected void onDestroy() {
// 如果WebView中加載音頻後退出Activity音頻聲音無法消失,可通過以下方法解決
// rootLayout.removeView(webView);
// webView.destroy();
super.onDestroy();
}
}
下面是一個HTML的代碼,放在項目的assets目錄下:
<html>
<script language="javascript">
function wave() {}
</script>
<body>
<a onClick="MyJsInterface.testJS()">
<br>
Click me!
</a>
</body>
</html>