Android开发之android与JS互调 | Android与H5互调(附源码)
我們先看下JS代碼:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Js與Android交互</title> </head> <body> <H2>點(diǎn)擊獲取按鈕,彈出輸入框內(nèi)容</H2><div><span>輸入數(shù)據(jù):</span><input type="text" id="input"/></div> <div id="btn"><span class="btn">點(diǎn)我獲取數(shù)據(jù)</span></div><script type="text/javascript">var inputData = document.getElementById("input")var btn = document.getElementById("btn")//Js調(diào)用Android方法btn.addEventListener("click", function () {var getInputData = inputData.value;//androidJs這個(gè)方法必須和Android里面的方法保持一致if (window.androidJs) {//getJsData這個(gè)方法必須和Android里面的方法保持一致androidJs.getJsData(getInputData)} else {alert("與android互調(diào)方法不存在!")}});//Android調(diào)用Js的方法,writeInputText此方法需要跟android里面的方法保持一致var writeInputText = function (str) {inputData.value = str;//帶返回值的JS方法return '互調(diào)成功!'}</script> </body> </html>再來看下android代碼:
package kotlin.yhsh.cn.androidandjs;import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Button; import android.widget.EditText; import android.widget.TextView;/*** @author DELL* 2019年7月23日19:34:25*/ public class MainActivity extends Activity {private TextView tvShowData;private WebView wvLoadHtml;private EditText etInputToJs;private Button btClickInputToJs;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvShowData = findViewById(R.id.tv_show_data);wvLoadHtml = findViewById(R.id.wv_load_html);etInputToJs = findViewById(R.id.et_input_to_js);btClickInputToJs = findViewById(R.id.bt_click_input_to_js);btClickInputToJs.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String inputToJs = etInputToJs.getText().toString().trim();//if(window.writeInputText)判斷Js里面的writeInputText是否存在,存在就傳遞inputToJs這個(gè)值到Js里面//wvLoadHtml.loadUrl("javascript:if(window.writeInputText){window.writeInputText('" + inputToJs + "')}");//下面方法是Android4.4以后才可以用wvLoadHtml.evaluateJavascript("javascript:if(window.writeInputText){window.writeInputText('" + inputToJs + "')}", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {Log.e("打印互調(diào)", value + "=");}});}});WebSettings settings = wvLoadHtml.getSettings();settings.setJavaScriptEnabled(true);//方法一:androidJs這個(gè)方法必須和Js里面的方法保持一致wvLoadHtml.addJavascriptInterface(new OpenWebView(), "androidJs");//方法二: // wvLoadHtml.addJavascriptInterface(new GetWebViewData() { // @Override // @JavascriptInterface // public void getJsData(String data) { // getFinallyData(data); // } // }, "androidJs");//加載HTMLwvLoadHtml.loadUrl("file:///android_asset/loadAndroid.html");}/*** Js的回調(diào)結(jié)果方法*/class OpenWebView {/*** getJsData這個(gè)方法必須和Js里面的方法保持一致** @param data Js返回的數(shù)據(jù)*/@JavascriptInterfacepublic void getJsData(final String data) {getFinallyData(data);}}/*** getJsData這個(gè)方法必須和Js里面的方法保持一致*/interface GetWebViewData {/*** Js返回的數(shù)據(jù)** @param data 數(shù)據(jù)*/void getJsData(String data);}private void getFinallyData(final String data) {Log.e("打印拿到的數(shù)據(jù)", data);//當(dāng)前是子線程runOnUiThread(new Runnable() {@Overridepublic void run() {tvShowData.setText(data);}});} }再來看下xml布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayoutxmlns: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:orientation="vertical"tools:context=".MainActivity"><WebViewandroid:id="@+id/wv_load_html"android:layout_weight="1"android:layout_width="match_parent"android:layout_height="0dp"/><TextViewandroid:text="Js調(diào)用Android后顯示的數(shù)據(jù)"android:gravity="center"android:id="@+id/tv_show_data"android:layout_width="match_parent"android:layout_height="100dp"/><Viewandroid:background="@color/colorPrimary"android:layout_width="match_parent"android:layout_height="1dp"/><EditTextandroid:layout_marginTop="10dp"android:id="@+id/et_input_to_js"android:layout_width="match_parent"android:layout_height="wrap_content"/><Buttonandroid:text="android調(diào)用Js代碼"android:id="@+id/bt_click_input_to_js"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout>來看下效果圖:
JS調(diào)用android:
在HTML頁面輸入數(shù)據(jù),然后在最下面的textView控件顯示輸入內(nèi)容
再看下android調(diào)用JS:
看不懂的可自行下載源碼:源碼下載
另外附加GitHub下載地址:Android與JS互調(diào)源碼下載
總結(jié)如下:
Android與 js 是如何交互的
在 Android 中,Android 與js 的交互分為兩個(gè)方面:Android 調(diào)用 js 里的方法、js 調(diào)用 Android 中的方法;
Android調(diào)js。 Android 調(diào) js 有兩種方法:
-
WebView.loadUrl("javascript:js代碼")。 這種方法的優(yōu)點(diǎn)是很簡潔,缺點(diǎn)是沒有返回值,如果需要拿到j(luò)s方法的返回值則需要js調(diào)用Android中的方法來拿到這個(gè)返回值;
-
WebView.evaluateJavaScript("javascript:js中的方法名",ValueCallback)。 這種方法比 loadUrl 好的是可以通過 ValueCallback 這個(gè)回調(diào)拿到 js方法的返回值。缺點(diǎn)是這個(gè)方法 Android4.4 才有,兼容性較差。不過放在 2018 年來說,市面上絕大多數(shù) App 都要求最低版本是 4.4 了,所以我認(rèn)為這個(gè)兼容性問題不大;
js 調(diào) Android。 js 調(diào) Android有三種方法:
-
WebView.addJavascriptInterface()。 這是官方解決 js 調(diào)用 Android 方法的方案,需要注意的是要在供 js 調(diào)用的 Android 方法上加上 @JavascriptInterface 注解,以避免安全漏洞。這種方案的缺點(diǎn)是 Android4.2 以前會有安全漏洞,不過在 4.2 以后已經(jīng)修復(fù)了。同樣,在 2018 年來說,兼容性問題不大;
-
重寫 WebViewClient的shouldOverrideUrlLoading()方法來攔截url, 拿到 url 后進(jìn)行解析,如果符合雙方的規(guī)定,即可調(diào)用 Android 方法。優(yōu)點(diǎn)是避免了 Android4.2 以前的安全漏洞,缺點(diǎn)也很明顯,無法直接拿到調(diào)用 Android 方法的返回值,只能通過 Android 調(diào)用 js 方法來獲取返回值;
-
重寫 WebChromClient 的 onJsPrompt() 方法,同前一個(gè)方式一樣,拿到 url 之后先進(jìn)行解析,如果符合雙方規(guī)定,即可調(diào)用Android方法。最后如果需要返回值,通過 result.confirm("Android方法返回值") 即可將 Android 的返回值返回給 js。方法的優(yōu)點(diǎn)是沒有漏洞,也沒有兼容性限制,同時(shí)還可以方便的獲取 Android 方法的返回值。其實(shí)這里需要注意的是在 WebChromeClient 中除 了 onJsPrompt 之外還有 onJsAlert 和 onJsConfirm 方法。那么為什么不選擇另兩個(gè)方法呢?原因在于 onJsAlert 是沒有返回值的,而 onJsConfirm 只有 true 和 false 兩個(gè)返回值,同時(shí)在前端開發(fā)中 prompt 方法基本不會被調(diào)用,所以才會采用onJsPrompt;
總結(jié)
以上是生活随笔為你收集整理的Android开发之android与JS互调 | Android与H5互调(附源码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android开发面试题之activit
- 下一篇: Linux 精准获取进程pid--转