目錄
3.1 WebViewClient中的shouldOverrideUrlLoading攔截url
3.2 WebViewClient中的onPageStarted
3.3 WebViewClient中的onPageFinished
3.4 webview的evaluateJavascript方法
先上效果圖:
源碼地址:https://github.com/LucasXu01/Autils
一 混合開發簡介
原生app :java/kotlin 純原生寫出的app;
web app:web寫出的app;
hybird app:原生+web(通過webview)寫出的app;
當然,現在也有很多第三方混合開發框架以及簡便的js橋,但是作爲最基礎的webview,掌握js/android的互調等相關知識是非常必要的。
二 Android-Js互調
2.1 準備自己的html文件
安卓和html中js的互調,一是要有安卓代碼,二肯定需要html網頁。工程中,網頁都是放在服務器,方便隨時更改,用戶無需再次更新自己的app,已達到hybrid開發的目的,實例方便起見,將html文件放在了本地。
首先,在自己安卓項目中的app目錄下新建assets文件夾(若沒有):
接着,在assets文件夾下新建自己的html文件,代碼如下:
<html>
<head>
<meta http-equiv="Content-Type" charset="GB2312"/>
<script type="text/javascript">
function javacalljs(){
document.getElementById("showmsg").innerHTML = "JAVA調用了JS的無參函數";
}
function javacalljswith(arg){
document.getElementById("showmsg").innerHTML = (arg);
}
</script>
</head>
<body>
<h3 align="center">Web模塊</h3>
<h3 id="showmsg" align="center">調用js顯示結果</h3>
<div style="text-align:center; vertical-align:middle;">
<input type="button" value="Js調用Java代碼" οnclick="window.android.jsCallAndroid()"/>
</div>
<br>
<br>
<div style="text-align:center; vertical-align:middle;">
<input type="button" value="Js調用Java代碼並傳參數" οnclick="window.android.jsCallAndroidArgs('Js傳過來的參數')"/>
</div>
</body>
</html>
2.2 WebView控件的準備設置
在自己的activity活動中獲得webview控件後,需要進行以下設置:
WebSettings webSettings = webview.getSettings();
//與js交互必須設置
webSettings.setJavaScriptEnabled(true);
webview.loadUrl("file:///android_asset/html.html");
webview.addJavascriptInterface(MainActivity.this,"android");
- webSettings.setJavaScriptEnabled(true) 表示讓WebView支持調用Js;
- webview.loadUrl("file:///android_asset/html.html") 表示加載assets文件下的html.html文件(因爲沒有網絡地址所以加載的本地文件)
- webview.addJavascriptInterface(MainActivity.this,"android") 給webview添加Js調用接口,第一個參數爲類對象,第二個參數爲自定義別名,Js通過這個別名來調用Java的方法,我這裏自定義爲android。
html中用到:<input type="button" value="Js調用Java代碼" οnclick="window.android.jsCallAndroid()"/>
2.3 Android調用Js代碼
在android代碼中(如按鈕點擊事件中),通過webview這個中介調用loadUrl來執行html代碼中的Js代碼:
tvJs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webview.loadUrl("javascript:javacalljs()");
}
});
下爲html中要被安卓調用的js函數代碼,函數意圖爲:向id爲showmsg的h3大小標題中寫入字符串“JAVA調用了JS的無參函數”。
function javacalljs(){
document.getElementById("showmsg").innerHTML = "JAVA調用了JS的無參函數";
}
在上述基礎上,若要在Android調用Js函數時傳參數,只需要在loadUrl方法中進行字符串的拼接,將參數以字符串形式拼接進去即可。
webview.loadUrl("javascript:javacalljswith(" + "'Android傳過來的參數'" + ")");
2.4 Js調用Android方法和傳參數
點擊html按鈕,通過οnclick="window.android.jsCallAndroid()事件,通過android別名調用Java文件的jsCallAndroid()方法。曾經Js可直接調用Java代碼竊取App信息,爲安全起見,在Android4.4以上並且必須加入@JavascriptInterface纔有響應。
@JavascriptInterface
public void jsCallAndroid(){
tvShowmsg.setText("Js調用Android方法");
}
@JavascriptInterface
public void jsCallAndroidArgs(String args){
tvShowmsg.setText(args);
}
所有的activity代碼如下:
package com.lucas.autils.autils;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
/**
* 原生webview js與安卓互調
* @author lucas
* created at 2019/9/12 12:23 PM
*/
public class JsJavaActivity extends Activity {
private WebView webview;
private TextView tvJs;
private TextView tvJsArgs;
private TextView tvShowmsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jsjava);
setWebview();
initView();
}
private void initView() {
tvJs = (TextView) findViewById(R.id.tv_androidcalljs);
tvJsArgs = (TextView) findViewById(R.id.tv_androidcalljsargs);
tvShowmsg = (TextView) findViewById(R.id.tv_showmsg);
tvJs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webview.loadUrl("javascript:javacalljs()");
}
});
tvJsArgs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webview.loadUrl("javascript:javacalljswith(" + "'Android傳過來的參數'" + ")");
}
});
}
private void setWebview() {
webview = (WebView) findViewById(R.id.webview);
WebSettings webSettings = webview.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setSupportZoom(true);
//與js交互必須設置
webSettings.setJavaScriptEnabled(true);
webview.loadUrl("file:///android_asset/html.html");
webview.addJavascriptInterface(JsJavaActivity.this,"android");
}
@JavascriptInterface
public void jsCallAndroid(){
tvShowmsg.setText("Js調用Android方法");
}
@JavascriptInterface
public void jsCallAndroidArgs(String args){
tvShowmsg.setText(args);
}
}
三 常用的幾個方法和注意點
3.1 WebViewClient中的shouldOverrideUrlLoading攔截url
安卓webview中setWebViewClient方法中需要一個WebViewClient對象,而WebViewClient中有個方法爲shouldOverrideUrlLoading,通過此方法可以進行我們需要跳轉的url地址的攔截,並根據我們需要進行自定義化的一些操作,解析url做相應的事情。
3.2 WebViewClient中的onPageStarted
onPageStarted會在webview加載相應的url開始之前進行調用,常用來處理需要在加載相應url之前的一些操作。
3.3 WebViewClient中的onPageFinished
onPageStarted會在webview加載相應的url結束之後進行調用,常用來處理需要在加載相應url之後的一些操作,比如加載後更加網頁標題填充原生頁面最上方的活動標題。
3.4 webview的evaluateJavascript方法
該方法的執行不會使頁面刷新,而方法(loadUrl )的執行則會使頁面刷新。此Android 4.4 後纔可使用。
//攔截url
webview.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.indexOf("jump")>-1){
Toast.makeText(JsJavaActivity.this,"攔截到了相應url",Toast.LENGTH_LONG).show();
return true;
}else if (url.startsWith("http")){
view.loadUrl(url);
return true;
}
return false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
// 開始加載頁面時
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// 加載結束
//因爲該方法的執行不會使頁面刷新,而方法(loadUrl )的執行則會使頁面刷新。
//Android 4.4 後纔可使用
webview.evaluateJavascript("javascript:changename()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
//此處爲 js 返回的結果
Log.v("Native",value);
}
});
}
});