Android中實(shí)現(xiàn)WebView和JavaScript的互相調(diào)用詳解
前言
很多復(fù)雜的UI界面,在Android中需要配合大量xml代碼和java代碼實(shí)現(xiàn),而使用HTML5可以非常輕松的實(shí)現(xiàn)出來,而且具有很好的跨平臺(tái)特性,讓我們不必為了多個(gè)平臺(tái)而重寫代碼,H5學(xué)習(xí)成本也較低,上手快。雖然從目前來說H5在Android系統(tǒng)中的速度可能還欠佳一些,但相信隨著手機(jī)的性能不斷的提高,這些問題都會(huì)被解決
使用H5開發(fā)Android的UI界面,最重要的就是如何實(shí)現(xiàn)Js代碼和Java代碼之間的互相調(diào)用了
在講解之前,讓我們先把項(xiàng)目跑起來
效果圖:

準(zhǔn)備好index.html文件,將它放入Android工程下的assets文件夾中:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSTest</title> <script src="app.js"></script> </head> <body> <table border="1" width="100%" id="table" cellspacing="0"> <tr> <td width="50%" align="center">姓名</td> <td width="50%" align="center">電話</td> </tr> </table> <hr> <input id="jsinput"> <Button onclick="getMessage()">js傳值給Toast</Button> </body> </html>
JavaScript的代碼我單獨(dú)寫在一個(gè)js文件中了,把a(bǔ)pp.js文件也放入assets文件夾中:
function getMessage(){
var message = document.getElementById("jsinput");
contact.showToast(message.value);
}
function addPerson(persons){
var personObjs = eval(persons);
var table = document.getElementById("table");
for(var i=0; i < personObjs.length; i++){
var tr = table.insertRow(table.rows.length);
var td1 = tr.insertCell(0);
td1.align = "center";
var td2 = tr.insertCell(1);
td2.align = "center";
td1.innerHTML = personObjs[i].name;
td2.innerHTML = personObjs[i].phone;
}
}
最后就是Java代碼
public class MainActivity extends AppCompatActivity {
private WebView mWebView;
private Button mJsMethodBtn;
private JsObject jsobj;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mJsMethodBtn = (Button) findViewById(R.id.btn_js_method);
mWebView = (WebView) findViewById(R.id.web_view);
mWebView.loadUrl("file:///android_asset/index.html");
WebSettings setting = mWebView.getSettings();
setting.setJavaScriptEnabled(true);
setting.setDefaultTextEncodingName("utf-8");
jsobj = new JsObject();
mWebView.addJavascriptInterface(jsobj, "contact");
mJsMethodBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 添加一個(gè)聯(lián)系人
jsobj.addPerson();
}
});
}
private class JsObject {
// 此方法被js調(diào)用
@JavascriptInterface
public void showToast(String message) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
// 在Web頁(yè)面增加一個(gè)聯(lián)系人
public void addPerson() {
String json = "[{\"name\":\"zwt\",\"phone\":\"15949999999\"}]";
mWebView.loadUrl("javascript:addPerson('" + json + "')");
}
}
}
還有布局代碼:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#EED5B7" android:orientation="vertical"> <WebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="360dp"/> <Button android:id="@+id/btn_js_method" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="調(diào)用js方法"/> </LinearLayout>
一、JavaScript調(diào)用Android中的方法
這里實(shí)現(xiàn)的場(chǎng)景是點(diǎn)擊Web頁(yè)面中的Button,把input中輸入的數(shù)據(jù)傳遞給Android系統(tǒng),并通過Toast顯示出來
對(duì)應(yīng)的js代碼:
function getMessage(){
var message = document.getElementById("jsinput");
contact.showToast(message.value);
}
對(duì)應(yīng)的java代碼:
// 此方法被js調(diào)用
@JavascriptInterface
public void showToast(String message) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
其中的“contact”其實(shí)指的就是我們?cè)趈ava代碼中定義的JsObject類
他倆通過以下方法實(shí)現(xiàn)綁定:
mWebView.addJavascriptInterface(jsobj, "contact");
第一個(gè)參數(shù)傳入的是一個(gè)java對(duì)象,第二參數(shù)是指定對(duì)應(yīng)的js里調(diào)用該類時(shí)需要使用的自定義別名,這個(gè)方法的作用就是將一個(gè)Java對(duì)象和JavaScript聯(lián)系起來
這里需要注意個(gè)問題,在SDK17以上的版本中,google為了安全考慮,只允許js調(diào)用帶有@JavascriptInterface注解的Java方法,所以我們要給被js調(diào)用的java方法前加上@JavascriptInterface注解
二、Android調(diào)用JavaScript中的方法
用戶點(diǎn)擊Android中的Button控件后,傳一個(gè)json數(shù)據(jù)給JavaScript方法,js解析json數(shù)據(jù)后添加一個(gè)新的聯(lián)系人顯示在Web頁(yè)面上
對(duì)應(yīng)的js代碼:
function addPerson(persons){
var personObjs = eval(persons);
var table = document.getElementById("table");
for(var i=0; i < personObjs.length; i++){
var tr = table.insertRow(table.rows.length);
var td1 = tr.insertCell(0);
td1.align = "center";
var td2 = tr.insertCell(1);
td2.align = "center";
td1.innerHTML = personObjs[i].name;
td2.innerHTML = personObjs[i].phone;
}
}
對(duì)應(yīng)的java代碼:
// 在Web頁(yè)面增加一個(gè)聯(lián)系人
public void addPerson() {
String json = "[{\"name\":\"zwt\",\"phone\":\"15949999999\"}]";
mWebView.loadUrl("javascript:addPerson('" + json + "')");
}
想要調(diào)用JavaScript中的某個(gè)方法,使用以下方法的標(biāo)準(zhǔn)格式就可以了:
mWebView.loadUrl("javascript:xxxMethod()");
“xxxMethod()”指的是JavaScript中的某個(gè)方法,如需調(diào)用其它方法,只要把后面的xxxMethod()替換成js中對(duì)應(yīng)的方法就好
三、常見問題
1.Android與js互調(diào)不成功
- 給WebView的setJavaScriptEnabled方法設(shè)置為true,使其允許js代碼執(zhí)行
- 在API高于17的版本上,需要被js調(diào)用的java方法前加上@JavascriptInterface
- 檢查js中的別名是否寫錯(cuò),調(diào)用java方法時(shí)類的別名,一定要是mWebView.addJavascriptInterface(jsobj, “contact”);里面定義的別名
2.網(wǎng)頁(yè)的alert彈不出
需要重寫WebChromeClient中的onJsAlert()方法
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
});
如果需要把web頁(yè)面的alert彈出框替換成Android的AlertDialog,可以在onJsAlert()方法里進(jìn)行重寫,并設(shè)置return為true
3.Js調(diào)用java方法修改UI界面不成功
只要明白這一點(diǎn):js調(diào)用的java方法,其實(shí)是運(yùn)行在另外一個(gè)子線程WebViewCoreThread中
測(cè)試一下:把以下語(yǔ)句分別放在Activity的onCreate()方法里和被js調(diào)用的java方法中
Log.e(TAG, "運(yùn)行線程name->" + Thread.currentThread().getName());
當(dāng)onCreate執(zhí)行時(shí)運(yùn)行的log:
運(yùn)行線程name->main
當(dāng)JsObject類中的方法運(yùn)行時(shí)的log:
運(yùn)行線程name->WebViewCoreThread
很明顯,子線程不允許修改主線程UI,所以我們想通過js調(diào)用java代碼直接修改UI界面的做法是不被允許的
如果需要修改,可以通過Handler機(jī)制去解決
4.如何讓手機(jī)的返回鍵跳到上一個(gè)Web頁(yè)面
如果不對(duì)手機(jī)系統(tǒng)的返回鍵進(jìn)行處理,那么我們按返回鍵會(huì)直接關(guān)閉當(dāng)前Activity,而不會(huì)回到上一個(gè)Web頁(yè)面
解決這個(gè)問題,我們可以重寫Activity中的onBackPressed()方法:
@Override
public void onBackPressed() {
super.onBackPressed();
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
finish();
}
}
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- 三步搞定:Vue.js調(diào)用Android原生操作
- DCloud的native.js調(diào)用系統(tǒng)分享實(shí)例Android版代碼
- Android WebView的使用方法及與JS 相互調(diào)用
- Android編程使用WebView實(shí)現(xiàn)與Javascript交互的方法【相互調(diào)用參數(shù)、傳值】
- JS調(diào)用Android、Ios原生控件
- Android總結(jié)之WebView與Javascript交互(互相調(diào)用)
- Android與JS之間跨平臺(tái)異步調(diào)用實(shí)例詳解
- Android webview和js互相調(diào)用實(shí)現(xiàn)方法
- Android WebView使用方法詳解 附j(luò)s交互調(diào)用方法
- Android與JS相互調(diào)用的方法
相關(guān)文章
DownloadManager實(shí)現(xiàn)文件下載功能
這篇文章主要為大家詳細(xì)介紹了DownloadManager實(shí)現(xiàn)文件下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
android使用Ultra-PullToRefresh實(shí)現(xiàn)下拉刷新自定義代碼
本篇文章主要介紹了android使用Ultra-PullToRefresh實(shí)現(xiàn)下拉刷新新自定義,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02
Flutter音樂播放插件audioplayers使用步驟詳解
audioplayers是一個(gè)可以支持同時(shí)播放多個(gè)音頻文件的Flutter的插件,可以播放多個(gè)同時(shí)的音頻文件,這篇文章主要介紹了audioplayers的使用步驟,感興趣想要詳細(xì)了解可以參考下文2023-05-05
避免 Android中Context引起的內(nèi)存泄露
本文主要介紹Android中Context引起的內(nèi)存泄露的問題,這里對(duì)Context的知識(shí)做了詳細(xì)講解,說明如何避免內(nèi)存泄漏的問題,有興趣的小伙伴可以參考下2016-08-08
android 使用瀏覽器打開指定頁(yè)面的實(shí)現(xiàn)方法
這篇文章主要介紹了android 使用瀏覽器打開指定頁(yè)面的實(shí)現(xiàn)方法,本文通過實(shí)例文字說明的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06
Android實(shí)現(xiàn)保存QQ賬號(hào)與密碼功能(文件存儲(chǔ))
這篇文章主要介紹了Android保存QQ賬號(hào)與密碼,文件存儲(chǔ)是Android中最基本的一種數(shù)據(jù)存儲(chǔ)方式,它與Java中的文件存儲(chǔ)類似,都是通過I/O流形式把數(shù)據(jù)直接存儲(chǔ)到文件中,下面我們一起來看一下如何用Android實(shí)現(xiàn)文件存儲(chǔ)功能吧2022-04-04
Android實(shí)現(xiàn)短信驗(yàn)證功能的代碼
這篇文章主要介紹了Android實(shí)現(xiàn)短信驗(yàn)證功能的代碼的相關(guān)資料,需要的朋友可以參考下2016-07-07
五分了解Android?Progress?Bar進(jìn)度條加載
這篇文章主要為大家介紹了Android?Progress?Bar進(jìn)度條加載的實(shí)現(xiàn)及屬性示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Android編程實(shí)現(xiàn)兩點(diǎn)觸控功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)兩點(diǎn)觸控功能的方法,涉及Android事件響應(yīng)與處理相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
基于popupWindow實(shí)現(xiàn)懸浮半透明效果
這篇文章主要為大家詳細(xì)介紹了基于popupWindow實(shí)現(xiàn)懸浮半透明效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04

