1. 程式人生 > >通過WebView與H5進行完美互動

通過WebView與H5進行完美互動

此篇講解的是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;
            }
        }
    });

擴充套件文章:

借鑑文章: