Open youngwind opened 8 years ago
我们知道,如果想要满足飞快增长的业务需要,必然得在APP中嵌入Web内容。一般来说,是java调用webview类新建一个webview,然后通过loadUrl加载Web页面。如果这个页面是纯展示性的还好说,对于复杂的页面,常常需要调用APP原生的功能,这个时候应该怎么办呢?
我们把问题抽象一下:“如何实现javascript和java的相互调用?” 把问题一分为二,先来看“如何实现javascript调用java?”
我们要实现的效果如下图所示,点击某个按钮,打开一个新页面,然后加载web页面。点击web页面当中的按钮,调用安卓原生的方法toast,弹出提示。
如果你想在手机上查看真实效果的话,可以扫描下面的二维码安装测试包。
我们来想想如何实现上面的功能。难点有这么几个:
对于第一点,不是本文的重点,你可以参考这个链接来自行解决。
对于第二点,我们继续分析。 web和android,就像是一个中国人和一个美国人。想要不同语言之间的人进行有效沟通的话,必须要满足以下两个基本要素。
先来看动作监听。javascript的哪些操作会被java捕获到?整个web页面都是运行在java提供的webview实例当中。javascript执行以下四种行为会被webview监听到,箭头后面是对应触发的Java方法。
好,动作监听我们解决了。接下来是要制定通信协议。说到通信协议,我们首先想到的是http协议,没错,我们可以仿照http协议制定我们自己的协议。 比如http协议是这样子的: http://www.baidu.com?param 我们制定的协议是这样子: ywjs://toast?message 其中ywjs是scheme,代表我们用的是某种自定义的协议。toast是方法名,也就是我希望调用的是系统的toast方法。toast方法所需要的参数,也就是弹出的提示字符串。
好,思路我们已经分析好了。万事俱备,只欠敲代码了。(如果完全看不懂,请先补充一下基本的安卓开发知识和webview的使用方法)
// java代码 JSBridgeAlert.java package com.example.youngwind.helloworld.JSBridgeAlert; import android.content.pm.ApplicationInfo; import android.net.Uri; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import com.example.youngwind.helloworld.R; public class JSBridgeAlert extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_jsbridge_alert); // 添加了chrome:inspect bebug功能 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (0 != (getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE)) { WebView.setWebContentsDebuggingEnabled(true); } } final WebView myWebView = (WebView) findViewById(R.id.webView); // webview启用javascript WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true); myWebView.loadUrl("file:///android_asset/alert.html"); myWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { // message === "ywjs://toast?利用jsAlert建立JSBridge" if(message.startsWith("ywjs://")){ String methodName = ""; String param = ""; Uri uri = Uri.parse(message); // toast methodName = uri.getHost(); // msg参数 param = uri.getQuery(); if (methodName.equals("toast")) { Toast.makeText(view.getContext(), param, Toast.LENGTH_LONG).show(); } // 这一句非常关键,相当于点击了alert的确认 // 没有这一句的话,alert只能被触发一次,且其他地方的alert也不能被触发 result.confirm(); } return true; } }); } }
// html代码 Alert.html <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>利用jsAlert建立JSBridge</title> <style> #test { width:100%; height:50px; } </style> </head> <body> <button id="test">点我toast</button> <script src="file:///android_asset/jquery.js" type="text/javascript"></script> <script type="text/javascript"> $(document).on('click','#test',function(){ alert("ywjs://toast?利用jsAlert建立JSBridge"); }) </script> </body> </html>
刚刚只展示了onJsAlert的实现代码,就像刚刚提到的,还有confirm、prompt和location方法也可以用来实现。 另外,webview本身提供了这样的接口,可以不采用上面的重新思路来进行,那就是addJavascriptInterface。 具体的实现方法可以参考文末的链接,可以查看我编写的demo代码。
还有这么一些问题没有有待解决。
addJavascriptInterface和制定的协议有什么区别?
addJavascriptInterface
制定的协议
问题
我们知道,如果想要满足飞快增长的业务需要,必然得在APP中嵌入Web内容。一般来说,是java调用webview类新建一个webview,然后通过loadUrl加载Web页面。如果这个页面是纯展示性的还好说,对于复杂的页面,常常需要调用APP原生的功能,这个时候应该怎么办呢?
我们把问题抽象一下:“如何实现javascript和java的相互调用?” 把问题一分为二,先来看“如何实现javascript调用java?”
要实现的效果
我们要实现的效果如下图所示,点击某个按钮,打开一个新页面,然后加载web页面。点击web页面当中的按钮,调用安卓原生的方法toast,弹出提示。
如果你想在手机上查看真实效果的话,可以扫描下面的二维码安装测试包。
思路分析
我们来想想如何实现上面的功能。难点有这么几个:
对于第一点,不是本文的重点,你可以参考这个链接来自行解决。
对于第二点,我们继续分析。 web和android,就像是一个中国人和一个美国人。想要不同语言之间的人进行有效沟通的话,必须要满足以下两个基本要素。
先来看动作监听。javascript的哪些操作会被java捕获到?整个web页面都是运行在java提供的webview实例当中。javascript执行以下四种行为会被webview监听到,箭头后面是对应触发的Java方法。
好,动作监听我们解决了。接下来是要制定通信协议。说到通信协议,我们首先想到的是http协议,没错,我们可以仿照http协议制定我们自己的协议。 比如http协议是这样子的: http://www.baidu.com?param 我们制定的协议是这样子: ywjs://toast?message 其中ywjs是scheme,代表我们用的是某种自定义的协议。toast是方法名,也就是我希望调用的是系统的toast方法。toast方法所需要的参数,也就是弹出的提示字符串。
代码实现
好,思路我们已经分析好了。万事俱备,只欠敲代码了。(如果完全看不懂,请先补充一下基本的安卓开发知识和webview的使用方法)
其他实现方式
刚刚只展示了onJsAlert的实现代码,就像刚刚提到的,还有confirm、prompt和location方法也可以用来实现。 另外,webview本身提供了这样的接口,可以不采用上面的重新思路来进行,那就是addJavascriptInterface。 具体的实现方法可以参考文末的链接,可以查看我编写的demo代码。
遗留问题
还有这么一些问题没有有待解决。
参考资料