Skip to content

CoderMacro/AndroidJSInterface

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 

Repository files navigation

AndroidJSInterface

此项目,主要演示Android的WebView视图中,Native Call JavaScript、以及JavaScript Call Native的几种方式。


写在前面: Hybrid不可避免使用Native和JS交互,本文主要总结一下Android和JavaScript交互的解决方方。

[TOC]

A、Native调用JavaScript

方案一:调用loadUrl执行一段js
mWebView.loadUrl("javascript:alert('hello world')");
方案二:调用evaluateJavascript异步执行一段js
String jsString = "sum(a, b)";
mWebView.evaluateJavascript(js, new ValueCallback<String>() {
  @Override
  public void onReceiveValue(String s) {
    // 这里可以处理被调用js方法的return
  }
});
方案三:引用JsBridge框架
  • Web首先初始化WebViewJavascriptBridge,注册事件监听。
  • Web然后初始化接收函数回调,分为默认接收指定接收,responseCallback回调给Native信息
  • Native 调用Webview.send()WebView.callHandler()
//注册事件监听,初始化
function setupWebViewJavascriptBridge(callback) {
	if (window.WebViewJavascriptBridge) {
		callback(WebViewJavascriptBridge)
	} else {
		document.addEventListener(
                'WebViewJavascriptBridgeReady',
                function() {
                    callback(WebViewJavascriptBridge)
                },
                false
        );
    }
}

//回调函数,接收java发送来的数据
setupWebViewJavascriptBridge(function(bridge) {
   //默认接收
	bridge.init(function(message, responseCallback) {
		// 处理接收到消息
	});

	//指定接收,
	bridge.registerHandler("JSFUCN", function(data, responseCallback) {
		// 处理接收到消息
	});
})
    // 默认接收
    private void callJavaScriptDefaut() {
        mWebView.send("发送数据给js默认接收, new CallBackFunction() {
            @Override
            public void onCallBack(String data) { //处理js回传的数据
               
        });
    }
    // 指定接收
    private void callJavaScriptSpec() {
   

        mWebView.callHandler("JSFUCN", "发送数据给js指定接收", new CallBackFunction() {
            @Override
            public void onCallBack(String data) { //处理js回传的数据
               
            }
        });
    }

利用 webview调用js需要注意一下几点

  • WebSettings设置支持javascript
// 设置在类之前
@SuppressLint("SetJavaScriptEnabled") 
mWebView.getSettings().setJavaScriptEnabled(true);
  • 在运行Js脚本前,要有document对象,至少得load一个空白页
webView.loadData("","text/html","UTF-8");
  • 如果还是不行的话,就应该是因为第一个还没执行完呢 - 从界面按钮调用 - 延时调用 - 在onPageFinished中调用
webView.loadData(“”,"text/html","UTF-8");
webView.loadUrl("javascript:alert('hello')");
  • 必须实现WebChromeClient、WebViewClient
webView.setWebViewClient(new WebViewClient());
webView.setWebChromeClient(new WebChromeClient());
  • 使用JSBridge不用实现WebViewClient

B、JavaScript调用Native

方案一:拦截跳转
  • WebViewClient重载shouldOverrideUrlLoading 拦截URL

Web代码

function openMyBlogNewTarget() {
    window.open('https://www.jianshu.com/u/263c210b047c')
}

function openMyBlog() {
    window.location.href = 'https://www.jianshu.com/u/263c210b047c'
}
<a href="http://www.baidu.com" title="baidu" target="_blank">新标签页打开百度</a>
<a href="http://www.baidu.com" title="baidu" >当前页打开百度</a>

<button onclick='openMyBlogNewTarget()'>新标签打开我的博客</button>
<button onclick="openMyBlog()">打开我的博客</button>

Android代码

private class MYWebViewClient extends  WebViewClient {
	@Override
	public void onPageStarted(WebView view, String url, Bitmap favicon) {
		super.onPageStarted(view, url, favicon);
	}
	
	// 新方法 API21以后
	@Override
	public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
		super.shouldOverrideUrlLoading(view, request);
		
		// 拦截Request
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
			Log.d(TAG, "shouldOverrideUrlLoading: " + request.getUrl().toString());
       }
		return true;
	}
        
   // 旧方法 兼容API21之前
	@Override
	public boolean shouldOverrideUrlLoading(WebView view, String url) {
		super.shouldOverrideUrlLoading(view, url);
		// 拦截url
		Log.d(TAG, "shouldOverrideUrlLoading: " + url);
		return true;
	}
}
方案二:JSInterface
  • JS中使用window.objects.function语法调用Native,其中objects与Native中一直。
  • Native中定义Class,以及被调用的func用 public、@JavascriptInterface修饰。
  • Native中addJavascriptInterface(obj, name)
function callNative() {
	var amount = 123.5;
	var orderno = "FG1afsdakewqr";
	window.mobileApp.toPay(amount, orderno);
}
<button onclick="window.mobileApp.sendMessage('特斯拉 Model 3')">获取商品名</button>
<button onclick="callNative()">支付按钮</button>
mWebView.addJavascriptInterface(new JsInterface(tv), "mobileApp");


private class JsInterface {

	private TextView showText;
	
	public JsInterface(TextView tv) {
		showText = tv;
	}

	@JavascriptInterface
	public void sendMessage(String msg) {
		Log.d(TAG, "sendMessage: " + msg);

	}
        
   @JavascriptInterface
	public void toPay(float amount, String oderno) {
		Log.d(TAG, "sendMessage: " + amount);
    }
}
方案三:引用JsBridge框架
  • JS中调用window.WebViewJavascriptBridge.send 或者 window.WebViewJavascriptBridge.callHandler 向Native发消息
  • Native中注册指定接收WebView.registerHandler或者注册默认接收WebView.setDefaultHandler
//js传递数据给java
function jsCallNativeDefault() {
	window.WebViewJavascriptBridge.send({ 'param': "str1" },	function(responseData) { //处理java回传的数据

	});
}

function jsCallNativeSpec() {
	window.WebViewJavascriptBridge.callHandler(
	'Spec' //指定接收参数 submitFromWeb与java一致
	,'指定接收'
	,function(responseData) { //处理java回传的数据
	
	 });
}
mWebView.registerHandler("Spec", new BridgeHandler() {
	@Override
	public void handler(String data, CallBackFunction function) {
		Log.i("", "handler = submitFromWeb, data from web = " + data);
		function.onCallBack("submitFromWeb exe, response data 中文 from Java");
			showTextView.setText("指定接收:" + data);
		}
});

mWebView.setDefaultHandler(new DefaultHandler() {
	@Override
	public void handler(String data, CallBackFunction function) {
		Log.i("", "handler = submitFromWeb, data from web = " + data);
		function.onCallBack("submitFromWeb exe, response data 中文 from Java");
			showTextView.setText("默认接收:" + data);
		}
});

About

此项目,主要演示Android的WebView视图中,Native Call JavaScript、以及JavaScript Call Native的几种方式。

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published