JsBridge实现JavaScript和Android的互相调用

Android的WebView是基于webkit内核的,WebView中集成了JS与Java互调的接口函数,通过addJavascriptInterface(Object obj, String interfaceName)方法,可以将Java的类注册进webkit,给网页上的JS进行调用,而且还可以通过loadUrl(String url)方法是给webkit传递一个uri,供浏览器来进行解析,实现Java和JS方法的交互。

更多详细的文档介绍可以参考Android Developers中关于WebView的详细介绍,链接如下:http://developer.android.com/guide/webapps/webview.html

这里列举一个简单的例子来示例一下WebView与JS之间的交互流程,如有写的不足的地方,欢迎大家拍砖!

WebViewDemo 源代码如下:

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class WebViewDemo extends Activity {
	
	public static final String TAG = WebViewDemo.class.getSimpleName();
	
	private Handler mHandler = new Handler();
	private WebView mWebView;  
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		setContentView(R.layout.activity_main);
		super.onCreate(savedInstanceState);
		
		initView();  
	}
	
	@SuppressLint("SetJavaScriptEnabled")
	private void initView() {
		mWebView = (WebView) findViewById(R.id.mWebView);
		//WebSettings 几乎浏览器的所有设置都在该类中进行  
        WebSettings webSettings = mWebView.getSettings();  
        webSettings.setSavePassword(false);  
        webSettings.setSaveFormData(false);  
        webSettings.setJavaScriptEnabled(true);  
        webSettings.setSupportZoom(false);  
        
        mWebView.setWebViewClient(new MyWebViewClient());
        mWebView.setWebChromeClient(new MyWebChromeClient());  
        /* 
         * DemoJavaScriptInterface类为js调用android服务器端提供接口 
         * android 作为DemoJavaScriptInterface类的客户端接口被js调用 
         * 调用的具体方法在DemoJavaScriptInterface中定义: 
         * 例如该实例中的clickOnAndroid 
         */  
        mWebView.addJavascriptInterface(new DemoJavaScriptInterface(),"Android");  
        mWebView.loadUrl("file:///android_asset/page.html");
	}
	
	/**
	 * 继承WebViewClient类,对WebView中页面开始加载、页面加载完毕、页面加载出错、url拦截等事件的处理
	 * @author Bingbing Feng
	 *
	 */
	final class MyWebViewClient extends WebViewClient{

		@Override
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
			Log.i(TAG, "shouldOverrideUrlLoading url="+url);
			return super.shouldOverrideUrlLoading(view, url);
		}

		@Override
		public void onPageStarted(WebView view, String url, Bitmap favicon) {
			Log.i(TAG, "onPageStarted url="+url);
			super.onPageStarted(view, url, favicon);
		}

		@Override
		public void onPageFinished(WebView view, String url) {
			Log.i(TAG, "onPageFinished url="+url);
			super.onPageFinished(view, url);
		}

		@Override
		public void onReceivedError(WebView view, int errorCode,
				String description, String failingUrl) {
			Log.e(TAG, "onReceivedError errorCode="+errorCode);
			super.onReceivedError(view, errorCode, description, failingUrl);
		}
		
	}

	/**
	 * 继承WebChromeClient类,对js弹出框事件进行处理 
	 * @author Bingbing Feng
	 *
	 */
    final class MyWebChromeClient extends WebChromeClient {

		@Override
		public void onProgressChanged(WebView view, int newProgress) {
			Log.i(TAG, "onProgressChanged newProgress="+newProgress);
			super.onProgressChanged(view, newProgress);
		}

		@Override
		public boolean onJsAlert(WebView view, String url, String message,
				JsResult result) {
			Log.i(TAG, "onJsAlert message="+message);
            //对alert的简单封装  
            new AlertDialog.Builder(WebViewDemo.this).  
                setTitle("Alert").setMessage(message)
            .setPositiveButton("OK",  
                new DialogInterface.OnClickListener() {  
                    @Override  
                    public void onClick(DialogInterface arg0, int arg1) {  
                    	// TODO Auto-generated method stub
                    	
                   }  
            })
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					
				}
			})
            .create().show();  
            result.confirm();  //一定不能少
            return true;  
		}

		@Override
		public boolean onJsConfirm(WebView view, String url, String message,
				JsResult result) {
			Log.i(TAG, "onJsAlert message="+message);
			return super.onJsConfirm(view, url, message, result);
		}

		@Override
		public boolean onJsPrompt(WebView view, String url, String message,
				String defaultValue, JsPromptResult result) {
			Log.i(TAG, "onJsAlert message="+message);
			return super.onJsPrompt(view, url, message, defaultValue, result);
		}  
    }
	
	final class DemoJavaScriptInterface {  
		
        DemoJavaScriptInterface() {}  
  
        /** 
         * 该方法被浏览器端调用 
         * Caution: If you've set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface
         */  
        @JavascriptInterface
        public void clickOnAndroid() {  
            mHandler.post(new Runnable() {  
                public void run() {  
                    //native调用js中的onJsAndroid方法  
                    mWebView.loadUrl("javascript:onJsAndroid()");  
                }  
            });  
        }  
        
        /** JS调用native方法显示一个Toast */
        @JavascriptInterface
        public void showToast(String toast) {
            Toast.makeText(getApplicationContext(), toast, Toast.LENGTH_SHORT).show();
        }
    }  
}


绑定一个回调的代理类JavaScriptInterface,并给它一个调用的名称Android

mWebView.addJavascriptInterface(new DemoJavaScriptInterface(),"Android");  

WebView addJavascriptInterface(Object obj, String interfaceName) 为javascript提供一个回调的接口,这里要注意,一定要在单独的线程中实现,要不会阻塞线程的。
addJavascriptInterface(Object obj, String interfaceName) 中obj代表一个java对象,这里我们一般会实现一个自己的类,类里面提供我们要提供给javascript访问的方法,interfaceName则是访问我们在obj中声明的方法时候所用到的js对象,调用模式为window.interfaceName.方法名()。

通过Log信息我们会发现回调接口中的方法(Obj 对象中提供给javascript访问的方法)运行在一个名为WebViewCoreThread的线程中,而不是main线程(UI线程),如果回调方法中需要执行某些耗时操作,建议在一个新的线程中去执行这些耗时操作。

Java调用HTLM页面中的JS方法,只需知道JS的方法名称即可:

mWebView.loadUrl("javascript:onJsAndroid()");  

接下来,我们看看如何在HTML页面中调起Native方法,示例代码如下:




WebView与JS方法交互










	

	




到这里WebView与JS的交互就已经完成了,大家可以动手实验一下!





你可能感兴趣的:(Android)