AndroidWebView、JavascriptInterface

目录

1.
2.AndroidWebView
3.JavascriptInterface
4.code




源码开发环境 JDK1.7
服务端环境 myeclipse10 Java EE6
Android环境 AndroidStudio1.5

Demo CSDN http://download.csdn.net/detail/linjiqian/9734627




1

Android一般使用WebView.loadUrl(url);加载指定的网页文件展示,并且可以实现javascript脚本与本地java代码的交互。
  原生应用在UI效果及运行效率上高于WebView,但是如果原生应用程序更改UI就需要用户更新手机上的APP才能体验到,而WebView充分解决了这个问题,这是混合移动开发最大优势,能把设计师最新的想法及时让用户体验,免去频繁更新APP的烦恼。
  混合移动开发时页面大部分可以使用WebView加载前端工程师已经写好的静态页面,而安卓工程师需要准备一些功能接口对安卓手机本身进行操作,前端可以通过js脚本调用本地java提供的接口,实现功能。
  静态页面有个打开手电筒的按钮,安卓工程师需写好打开手电筒的逻辑接口供js脚本调用,js脚本本身没有操作安卓API的能力。




2.AndroidWebView

使用WebView加载网页,JavaScript可以和本地Java代码相互调用。

AndroidWebView、JavascriptInterface_第1张图片
lwebview.gif

package lwebview.com.thing.www.view;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * Created by ThingLin on 2016/12/8.
 */
public class LWebView extends WebView {
    private Activity mActivity;
    private ProgressBar mProgressBar;
    private TextView mTextViewTitle;
    private View mBarLayout;
    private WebViewClientBase mWebViewClientBase = new WebViewClientBase();
    private WebChromeClientBase mWebChromeClientBase = new WebChromeClientBase();

    public LWebView(Context context) {
        super(context);
        mActivity = (Activity) context;
        init(context);
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void init(Context context) {
        //a WebSettings object that can be used to control this WebView's setting 该webview的设置
        WebSettings webSettings = this.getSettings();
        //true if the WebView should execute JavaScript  允许执行js
        webSettings.setJavaScriptEnabled(true);
        //whether the WebView should support zoom  开启缩放
        webSettings.setSupportZoom(true);
        //whether to enable support for the viewport meta tag  支持meta标记
        webSettings.setUseWideViewPort(true);

        //默认情况下,点击webview中的链接,会使用Android系统自带的浏览器打开这个链接。如果希望点击链接继续在我们自己的Browser中响应,必须覆盖 webview的WebViewClient对象
        this.setWebViewClient(mWebViewClientBase);

        this.setWebChromeClient(mWebChromeClientBase);
        this.onResume();
    }


    private class WebViewClientBase extends WebViewClient {

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
//            log("默认情况下,点击webview中的链接,会使用Android系统自带的浏览器打开这个链接。如果希望点击链接继续在我们自己的Browser中响应,必须覆盖 webview的WebViewClient对象");
            return super.shouldOverrideUrlLoading(view, url);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            //Notify the host application that a page has started loading  开始加载页面
            log("WebViewClient 开始加载页面 onPageStarted url="+url +" favicon="+favicon);
            if(null != mBarLayout){
                mBarLayout.setVisibility(View.VISIBLE);
            }
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            //Notify the host application that a page has finished loading  页面加载完成
            if(null != mBarLayout){
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mBarLayout.setVisibility(View.GONE);
                    }
                }, 500);
            }
            super.onPageFinished(view, url);
        }

        @Override
        public void onReceivedError(WebView view, int errorCode,
                                    String description, String failingUrl) {
            //Report an error to the host application. These errors are unrecoverable  出错
            log("WebViewClient onReceivedError  errorCode="+errorCode +",description="+description+" failingUrl="+failingUrl);
            super.onReceivedError(view, errorCode, description, failingUrl);
        }
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            log("WebViewClient  onReceivedError error= "+error);
            super.onReceivedError(view,request,error);
        }
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler,
                                       SslError error) {
            log("WebViewClient  onReceivedSslError  error="+error);
            super.onReceivedSslError(view, handler, error);
        }
        @Override
        public void onReceivedHttpError(
                WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
            log("WebViewClient onReceivedSslError  ");
            super.onReceivedHttpError(view,request,errorResponse);
        }

        @Override
        public void doUpdateVisitedHistory(WebView view, String url,
                                           boolean isReload) {
            //Notify the host application to update its visited links database.   reload重新加载
            log("WebViewClient doUpdateVisitedHistory  isReload="+isReload+ "  url="+url);
            super.doUpdateVisitedHistory(view, url, isReload);
        }
    }

    private class WebChromeClientBase extends WebChromeClient {

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
        //Tell the host application the current progress of loading a page. 页面加载进度
            if(null != mProgressBar){
                mProgressBar.setProgress(newProgress);
            }
        }

        @Override
        public void onReceivedTitle(WebView view, String title) {
            //Notify the host application of a change in the document title  文档标题
            if(null != mTextViewTitle){
                mTextViewTitle.setText(title);
            }
            super.onReceivedTitle(view, title);
        }

        @Override
        public boolean onCreateWindow(WebView view, boolean isDialog,
                                      boolean isUserGesture, Message resultMsg) {
            log("WebChromeClient  onCreateWindow  isUserGesture=" + isUserGesture + "    isDialog="+isDialog);
            return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
        }
    }


    public void setProgressBarView(ProgressBar progressBar){
        this.mProgressBar = progressBar;
    }

    public void setTitleTextView(TextView textView){
        this.mTextViewTitle = textView;
    }

    public void setBarLayout(View layout){
        this.mBarLayout = layout;
    }

    private void log(String log) {
        Log.e("LWebView", log);
    }

}





3.JavascriptInterface

通过WebView.addJavascriptInterface(Object object, String name)为WebView添加可供JS调用的本地方法。
  object参数的实现是一个普通的JavaClass,name参数会被绑定成为js中window对象的一个属性,该属性指向object参数,因此js中可以通过window.name.methodName()调用object对象有的本地方法。

Java本地调用js函数在android4.4之前使用WebView.loadUrl("javascript:methodName()");形式,这种形式js函数的返回值要再通过js调用本地java方法传递。android4.4可以使用WebView.evaluateJavascript("javascript:methodName()", new ValueCallback(){public void onReceiveValue(String value){} },js函数返回值在onReceiveValue回调函数中取得,evaluateJavascript方法必须在UI线程(主线程)调用,因此onReceiveValue也执行在主线程。

值得注意的是语言间通信还是一贯采用字符串形式传递参数和值,复杂数据类型使用json数据形式。

Java提供本地方法供JavaScript调用:


  mWebView.addJavascriptInterface(new JSCallJavaInterface(),"JSCallJava");

    /**
     * js调用java本地方法是子线程,需要注意
     */
    private final class JSCallJavaInterface{
        @JavascriptInterface
        public String callJava(final String msg){
            mHandler.post(new Runnable() {
                @TargetApi(Build.VERSION_CODES.KITKAT)
                @Override
                public void run() {
                    Log.d("MainActivity", "JS Call Java msg=" + msg);
                    String jsmethod = "javascript:javaCallJS(\'JavaCallJSMethod"+msg+"\')";
//          android 4.4 开始使用evaluateJavascript调用js函数 ValueCallback获得调用js函数的返回值
//                    mWebView.loadUrl(jsmethod);
                    mWebView.evaluateJavascript(jsmethod, new ValueCallback() {

                        @Override
                        public void onReceiveValue(String value) {
                            Log.d("MainActivity", "onReceiveValue value=" + value);
                        }
                    });
                }
            });
            return "Java result "+msg;
        }

//        android 4.4之前使用额外增加一个回调方法让js调用该函数返回函数结果,4.4开始可以使用ValueCallback
        @JavascriptInterface
        public void onJavaCallJSResult(String msg){
            Log.d("MainActivity","java call js result "+msg);
        }
    }

JavaScript调用Java本地方法:


a标签调用本地java

var result = window.JSCallJava.callJava('hello input click'); span_result.innerHTML = result;

4.code

MainActivity.java





package lwebview.com.thing.www.activity;

import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import lwebview.com.thing.www.view.LWebView;
import lwebview.com.thing.www.view.R;

public class MainActivity extends Activity {

    private LinearLayout mLayout;
    private LWebView mWebView;
    private ProgressBar mProgressBar;
    private TextView mTv_title;
    private LinearLayout mBar_layout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();
        initData();
        initEvent();
    }

    private void initView() {
        mLayout = (LinearLayout)View.inflate(this, R.layout.activity_main, null);
        setContentView(mLayout);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mTv_title = (TextView) findViewById(R.id.tv_title);
        mBar_layout = (LinearLayout) findViewById(R.id.bar_layout);

        mWebView = new LWebView(this);
        mWebView.clearCache(true);
        mWebView.setBarLayout(mBar_layout);
        mWebView.setProgressBarView(mProgressBar);
        mWebView.setTitleTextView(mTv_title);

        mWebView.setLayoutParams(new RelativeLayout.LayoutParams(-1, -1));
        mLayout.addView(mWebView);
    }

    private void initData() {
        mWebView.loadUrl("http://192.168.37.11/wv/w/html1.html");
    }

    private void initEvent() {
        mWebView.addJavascriptInterface(new JSCallJavaInterface(),"JSCallJava");
    }

    private Handler mHandler  = new Handler();

    /**
     * js调用java本地方法是子线程,需要注意
     */
    private final class JSCallJavaInterface{
        @JavascriptInterface
        public String callJava(final String msg){
            mHandler.post(new Runnable() {
                @TargetApi(Build.VERSION_CODES.KITKAT)
                @Override
                public void run() {
                    Log.d("MainActivity", "JS Call Java msg=" + msg);
                    String jsmethod = "javascript:javaCallJS(\'JavaCallJSMethod"+msg+"\')";
//          android 4.4 开始使用evaluateJavascript调用js函数 ValueCallback获得调用js函数的返回值
//                    mWebView.loadUrl(jsmethod);
                    mWebView.evaluateJavascript(jsmethod, new ValueCallback() {

                        @Override
                        public void onReceiveValue(String value) {
                            Log.d("MainActivity", "onReceiveValue value=" + value);
                        }
                    });
                }
            });
            return "Java result "+msg;
        }

//        android 4.4之前使用额外增加一个回调方法让js调用该函数返回函数结果,4.4开始可以使用ValueCallback
        @JavascriptInterface
        public void onJavaCallJSResult(String msg){
            Log.d("MainActivity","java call js result "+msg);
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //canGoBack()  有历史项目 为true  回退
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

html1.html





    
    
    html1
    


    
    html2.html
    

a标签调用本地java



jsCallJavaResult:
javaCallJS:












你可能感兴趣的:(AndroidWebView、JavascriptInterface)