通過WebView與H5進行完美互動
阿新 • • 發佈:2019-02-18
此篇講解的是Android通過WebView與H5的基礎互動,分直接呼叫無參方法與傳入方法引數。
文章目錄:
- Android呼叫Js,傳入Js需要的資料
- Js呼叫Android,觸發android功能,如拍照 亦或 跳轉Androi的一些介面
- 攔截HTML頁面中的點選事件
- 擴充套件文章與借鑑文章
目錄一 :Android呼叫Js,傳入Js需要的資料
方式一
- 這是我們要在App端展示的H5介面
- H5地址對應的程式碼
- 以下程式碼便是H5中的一個方法(PS:setVersion 為方法名)
<script type="text/javascript" >
function setVersion(version) {
document.getElementById("version").innerHTML = version
}
</script>
- Android中程式碼片段:
1.首先我們在onCreat生命週期內呼叫
//載入H5地址
mWebView.loadUrl("這裡輸入我們要呼叫的H5地址");
2.監聽WebView的載入狀態
/**
* 監聽WebView的載入狀態 分別為 : 載入的 前 中 後期
* */
mWebView.setWebViewClient(new WebViewClient() {
@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);
//獲取當前版本號
String versionName = DeviceUtils.getVersionName(AboutUsActivity.this);
//在載入完成之後,我們通過android的方法,去呼叫js的方法,設定對應的版本號
mWebView.loadUrl("javascript:setVersion('" + versionName + " ');");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//本應該載入的H5靜態介面
mWebView.loadUrl(url);
return true;
}
});
3.注意,呼叫了H5的方法傳入對應的引數
mWebView.loadUrl("javascript:setVersion('" + versionName + " ');");
Android完整程式碼 :
package com.bakheet.garage.mine.activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import com.bakheet.garage.R;
import com.bakheet.garage.base.BaseActivity;
import com.bakheet.garage.http.HttpUrl;
import com.bakheet.garage.utils.DeviceUtils;
/**
* @author Created by YongLiu on 2017/11/14.
*/
public class AboutUsActivity extends BaseActivity {
private WebView mWebView;
@Override
protected int getLayoutId() {
return R.layout.activity_about;
}
@Override
protected void init(Bundle savedInstanceState) {
setToolBarTitle(getString(R.string.title_about_us));
mWebView = (WebView) findViewById(R.id.web_agreement);
final ProgressBar mBar = (ProgressBar) findViewById(R.id.progress_Bar);
//允許Js的語言執行
mWebView.getSettings().setJavaScriptEnabled(true);
//載入本地H5
// mWebView.loadUrl("file:///android_asset/about.html");
//載入H5地址
mWebView.loadUrl(HttpUrl.ABOUT_H5 + "?timestamp=" + System.currentTimeMillis());
/**
* 監聽WebView的載入狀態 分別為 : 載入的 前 中 後期
* */
mWebView.setWebViewClient(new WebViewClient() {
@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);
String versionName = DeviceUtils.getVersionName(AboutUsActivity.this);
//在載入完成之後,我們通過android的方法,去呼叫js的方法,設定對應的版本號
mWebView.loadUrl("javascript:setVersion('" + versionName + " ');");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//本應該載入的H5靜態介面
mWebView.loadUrl(url);
return true;
}
});
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100) {
mBar.setVisibility(View.GONE);
} else {
mBar.setVisibility(View.VISIBLE);
mBar.setProgress(newProgress);
}
}
});
}
}
方式二(最低版本貌似要求19,但可嘗試此方式下Android端程式碼部分的第二份程式碼(註解部分))
- H5完整程式碼
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript">
function sum(a,b){
return a+b;
}
function s(){
var result =window.android.back();
document.getElementById("p").innerHTML=result;
}
</script>
</head>
<body>
<button onclick="s()">呼叫本地方法</button>
<a href="file:///android_asset/test2.html">點選</a>
<p id="p"></p>
</body>
</html>
- H5呼叫方法
<script type="text/javascript">
function sum(a,b){
return a+b;
}
function do(){
document.getElementById("p").innerHTML="hello world";
}
</script>
- Android程式碼:
mWebView.evaluateJavascript("sum(1,2)", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.e(TAG, "onReceiveValue value=" + value);
}
});
或
//Android呼叫有返回值js方法
@TargetApi(Build.VERSION_CODES.KITKAT)
public void onClick(View v) {
mWebView.evaluateJavascript("sum(1,2)", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.e(TAG, "onReceiveValue value=" + value);
}
});
}
目錄二 :Js呼叫Android,觸發android功能,如拍照 亦或 跳轉Androi的一些介面
Effect(已禁止LoginData.onBack()方法,所以不會觸發):
- H5程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button onclick="LoginData.onBack()">註冊方法</button>
<script type="text/javascript">
let button = document.querySelector('button')
let register = button.addEventListener('click', function () {
//LoginData.onBack();
LoginData.setData('18888888888','111111');
})
</script>
</body>
</html>
圖片講解:
- 優先注意
//可識別JS程式碼
mWebView.getSettings().setJavaScriptEnabled(true);
//對應Activity 新增以下程式碼 LoginData是一個承載類
//“LoginData”更像我們拋給前端同志的Api一樣
mWebView.addJavascriptInterface(new LoginData(this),"LoginData");
//因為給大家測試效果,我載入的本地的html!正常是載入前端給的
mWebView.loadUrl("file:///android_asset/register.html");
- 首先宣告一個類,內部用於儲存js要呼叫的方法
LoginData :
package com.bakheet.garage.mine.model;
import android.app.Activity;
import android.content.Intent;
import android.webkit.JavascriptInterface;
import com.alibaba.fastjson.JSON;
import com.bakheet.garage.base.MainActivity;
import com.bakheet.garage.http.HttpManager;
import com.bakheet.garage.http.ObjectResult;
import com.bakheet.garage.utils.SpUtil;
import com.bakheet.garage.utils.ToolUtil;
import java.io.IOException;
import java.util.HashMap;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Response;
/**
* author yongliu
* date 2018/4/19.
* desc:
*/
public class LoginData {
Activity mContext;
public LoginData(Activity mContext) {
this.mContext = mContext;
}
/**
* 暴露給JS的方法
*/
@JavascriptInterface
public void setData(String account, String password) {
//interLogin(account, password);
ToastUtils.shortShow("account ="+account+"password ="+password);
}
@JavascriptInterface
public void onBack(){
mContext.finish();
}
/**
* 登入請求 - 此條請忽略,這是我的專案需求
* */
private void interLogin(String account, String password) {
String mdPassword = ToolUtil.md5(password);
HashMap<String, String> map = new HashMap<>();
map.put("acc", account);
map.put("pwd", mdPassword);
String jsonParams = JSON.toJSONString(map);
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
Call<ObjectResult> login = HttpManager.getHttpService().getLogin(body);
HttpManager.enqueue(login, new HttpManager.OnResultListener<ObjectResult>() {
@Override
public void onSuccess(Call<ObjectResult> call, Response<ObjectResult> response) throws IOException {
String data = (String) response.body().getData();
SpUtil.putString("token", data);
Intent intent = new Intent(mContext, MainActivity.class);
mContext.startActivity(intent);
mContext.finish();
}
@Override
public void onError(Throwable t) {
}
});
}
}
注意:
//想要讓JS識別的話,必須在方法名上加 @JavascriptInterface 如:
//這裡我是用於監聽使用者在WebView中的點選事件,捕獲此事件,如捕獲成功關掉當前介面
@JavascriptInterface
public void onBack(){
mContext.finish();
}
- Activity程式碼
package com.bakheet.garage.home.activity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.ProgressBar;
import com.bakheet.garage.R;
import com.bakheet.garage.base.BaseActivity;
import com.bakheet.garage.mine.model.LoginData;
/**
* @author yongliu
* date 2018/4/16.
* desc:
*/
public class RegisterActivity extends BaseActivity {
private WebView mWebView;
@Override
protected int getLayoutId() {
return R.layout.activity_register;
}
@Override
protected void init(Bundle savedInstanceState) {
setToolBarTitle("註冊");
mWebView = (WebView) findViewById(R.id.web_register);
final ProgressBar mBar = (ProgressBar) findViewById(R.id.progress_Bar);
mWebView.getSettings().setJavaScriptEnabled(true);
// mWebView.loadUrl("file:///android_asset/about.html");
//載入H5地址
// mWebView.loadUrl(HttpUrl.REGISTER_H5);
mWebView.loadUrl("file:///android_asset/register.html");
mWebView.addJavascriptInterface(new LoginData(this), "LoginData");
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100) {
mBar.setVisibility(View.GONE);
} else {
mBar.setVisibility(View.VISIBLE);
mBar.setProgress(newProgress);
}
}
});
}
}
目錄 3:攔截HTML頁面中的點選事件
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//判斷url攔截事件
if (url.equals("file:///android_asset/test2.html")) {
Log.e(TAG, "shouldOverrideUrlLoading: " + url);
startActivity(new Intent(MainActivity.this,Main2Activity.class));
return true;
} else {
mWebView.loadUrl(url);
return false;
}
}
});
擴充套件文章:
借鑑文章: