1. 網頁端 JS 調用 Native APP 中的代碼
2. Native APP 調用 JS 端的代碼
3. 它們之間的數據傳遞如何實現
4. 代碼實現效果如下圖:
Manifest.xml 中添加權限
<uses-permission android:name="android.permission.INTERNET" />
MainActivity.java
package com.demo.thorn.jsandnativeappdemo; import android.content.DialogInterface; import android.content.Intent; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private WebView mWebView; private WebSettings mWebSettings; private Button btnDoJS; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnDoJS = findViewById(R.id.btn_fun); mWebView = findViewById(R.id.wv_content); mWebSettings = mWebView.getSettings(); mWebSettings.setJavaScriptEnabled(true); mWebSettings.setDefaultTextEncodingName("UTF-8"); mWebView.addJavascriptInterface(this,"androidTag");//傳入類對象,傳入 androidTag 作爲調用標誌 mWebView.setWebViewClient(new MyWebViewClient());//傳入 MyWebViewClient 對象,達到接收 HTML 傳遞的點擊動作 mWebView.setWebChromeClient(new MyWebChromeClient());//傳入 MyWebChormeClient 對象,達到對話框可用的目的 mWebView.loadUrl("file:///android_asset/test.html"); btnDoJS.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mWebView.loadUrl("javascript:doSomething()");// Activity 中調用 JS 的方法,可以加參數傳值 /* 如果調用 JS 時,需要獲得返回值,則調用 evaluateJavascript 這個方法,示例如下: mWebView.evaluateJavascript("sum(1,2)", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { Log.e(TAG, "onReceiveValue value=" + value); } }); */ } }); }//onCreate 結束 /*HTML 中被調用的方法*/ @JavascriptInterface public void showToast(String text) { Toast.makeText(this, text, Toast.LENGTH_LONG).show(); } /*HTML 中被調用的方法*/ @JavascriptInterface public void toAnotherAcitity(){ Intent intent2 = new Intent(MainActivity.this,SecondActivity.class); startActivity(intent2); } /*HTML 中被調用的方法*/ @JavascriptInterface public void showDialog() { new AlertDialog .Builder(this) .setTitle("Title Here") .setCancelable(true) .setNegativeButton("cacel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { showToast("negative"); } }) .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { showToast("positive"); } }) .setMessage("messages here ") .show(); } private class MyWebViewClient extends WebViewClient { /*官方文檔:Give the host application a chance to take over the control when a new url is about to be loaded in the current WebView.*/ /*在加載一個新的 URL 鏈接之前進行的操作(一般都是對一些 URL 進行攔截)*/ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(url.equals("http://www.qq.com/")){ showToast("攔截了 QQ 網站"); return true;// 返回 true 表示攔截本次跳轉;返回 false 表示繼續跳轉 }else if(url.endsWith("test")){ toAnotherAcitity(); return true; } return false; } /*如果加載某個頁面出錯,跳轉到本地的一個錯誤展示頁面*/ @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); mWebView.loadUrl("file:///android_asset/errorPage.html");//加載本地的錯誤頁面 Log.i("jin",error.toString()); } } //繼承 WebChromeClient 管理 JS 調用 Native APP 得事件 public class MyWebChromeClient extends WebChromeClient { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); Log.i("jin","title="+title.toString()); } } /*用於實現網頁瀏覽的“返回”功能*/ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(mWebView.canGoBack()&& keyCode == KeyEvent.KEYCODE_BACK){ mWebView.goBack(); return true; } return super.onKeyDown(keyCode, event); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.demo.thorn.jsandnativeappdemo.MainActivity"> <WebView android:layout_weight="1" android:id="@+id/wv_content" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:text="這裏 Activity 調用 JS" android:id="@+id/btn_fun" android:layout_width="match_parent" android:layout_height="50dp" /> </LinearLayout>
test.html(assets\test.html)
<html> <head> <meta charset="utf-8"/> <title>Js調用Android</title> </head> <body> <div> <dl> <dd><a href="http://www.qq.com">被攔截的URL</a></dd> <dd><a href="http://www.baidu.com">正常的URL</a></dd> <dd><a href="http://www.qq.test" >想在 shouldOverrideUrlLoading 中調用intent跳轉,但失敗了</a></dd> <dd><input type="button" value="調用方法NativeAPP中的方法跳轉" onclick="androidTag.toAnotherAcitity()"/></dd> <dd><input type="button" value="Toast 提示" onclick="androidTag.showToast('調用了 showToast 方法');"/></dd> <dd><input type="button" value="列表對話框" onclick="androidTag.showDialog();"/></dd> <dd> <input type="button" value="Alert" onclick="alertSomeThing()"/></dd> <dd><div id="content"><h2>這是初始內容</h2></div> </dd> </dl> </div> </body> <script> function alertSomeThing(){ // 彈出一個框 alert("alert something to show "); } function doSomething(){ //改變 id 爲 content 中的值 document.getElementById("content").innerHTML =("測試1111111111111"); } </script> </html>
errorPage.html(assets\errorPage.html)
<html> <head> <meta charset="utf-8"/> <title>ErrorPage</title> </head> <body> <a>不好意思,出錯了喲</a> </body> </html>
源代碼
https://github.com/ThornFUN/JsAndNativeAPPDemo