Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
来源:互联网 发布:淘宝店铺营销中心 编辑:程序博客网 时间:2024/05/29 03:10
此文出自:http://blog.csdn.net/sk719887916/article/details/47189607,skay
按安卓开发目前现状来说,开发者大部分时间还是花在UI的屏幕适配上,使用原生控件开发成本已不是那么理想,鉴于很多项目和ios基于一致的ui界面,至使安卓UI开发成本花费更大的代价,因此目前结合Html5和原生控件是解决UI适配的一种很好的选择,处于APP性能也会用java和native层进行结合。不管是哪种结合,其实原理都差不多,只要按照它的协议来,是很容易的,今天我们仅对于Html和Java层结合,学习下WebViewJavascriptBridge。
已经熟悉了jsbridge的朋友直接移步:
《Android基于JsBridge封装的高效带加载进度的WebView》:http://blog.csdn.net/sk719887916/article/details/52402470
一 什么是webViewjavascripBridge?
WebViewJavascriptBridge是移动UIView和Html交互通信的桥梁,用作者的话来说就是实现java(ios为oc)和js的互相调用的桥梁。替代了WebView的自带的JavascriptInterface的接口,使得我们的开发更加灵活和安全。
二 为什么要用webViewjavascripBridge?
mWebView.addJavascriptInterface(new JsToJava(), "myjsfunction");
4.4之后调用需要在调用方法加入加入@JavascriptInterface注解,如果代码无此申明,那么也就无法使得js生效,也就是说这样就可以避免恶意网页利用js对安卓客户端的窃取和攻击。
但是即使这样,我们很多时候需要在js记载本地代码的时候,要做一些判断和限制,或者有可能也会做些过滤和对用户友好提示,因此JavascriptInterface也就无法满足我们的需求了,特此有大神就写出了WebViewJavascriptBridge框架。
三 怎么使用webViewjavascripBridge
1 将jsBridge.jar引入到我们的工程
repositories { // ... maven { url "https://jitpack.io" }}dependencies { compile 'com.github.lzyzsd:jsbridge:1.0.4'}
2 WebView包需使用以上包的webView
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- button 演示Java调用web --> <Button android:id="@+id/button" android:layout_width="match_parent" android:text="@string/button_name" android:layout_height="48dp" /> <!-- webview 演示web调用Java --> <com.github.lzyzsd.jsbridge.BridgeWebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" > </com.github.lzyzsd.jsbridge.BridgeWebView></LinearLayout>
3 Java代码
public class MainActivity extends Activity implements OnClickListener {private final String TAG = "MainActivity";BridgeWebView webView;Button button;int RESULT_CODE = 0;ValueCallback<Uri> mUploadMessage; static class Location { String address; } static class User { String name; Location location; String testStr; }@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); webView = (BridgeWebView) findViewById(R.id.webView);button = (Button) findViewById(R.id.button);button.setOnClickListener(this);webView.setDefaultHandler(new DefaultHandler());webView.setWebChromeClient(new WebChromeClient() {@SuppressWarnings("unused")public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {this.openFileChooser(uploadMsg);}@SuppressWarnings("unused")public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {this.openFileChooser(uploadMsg);}public void openFileChooser(ValueCallback<Uri> uploadMsg) {mUploadMessage = uploadMsg;pickFile();}});//加载本地网页//webView.loadUrl("file:///android_asset/demo.html");//加载服务器网页webView.loadUrl("https://www.baidu.com");//必须和js同名函数,注册具体执行函数,类似java实现类。webView.registerHandler("submitFromWeb", new BridgeHandler() {@Overridepublic void handler(String data, CallBackFunction function) {String str ="这是html返回给java的数据:" + data;// 例如你可以对原始数据进行处理makeText(MainActivity.this, str, LENGTH_SHORT).show();Log.i(TAG, "handler = submitFromWeb, data from web = " + data); function.onCallBack( str + ",Java经过处理后截取了一部分:"+ str.substring(0,5));}});//模拟用户获取本地位置 User user = new User(); Location location = new Location(); location.address = "上海"; user.location = location; user.name = "Bruce"; webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) {makeText(MainActivity.this, "网页在获取你的位置", LENGTH_SHORT).show(); } }); webView.send("hello");}public void pickFile() {Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);chooserIntent.setType("image/*");startActivityForResult(chooserIntent, RESULT_CODE);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent) {if (requestCode == RESULT_CODE) {if (null == mUploadMessage){return;}Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();mUploadMessage.onReceiveValue(result);mUploadMessage = null;}}@Overridepublic void onClick(View v) {if (button.equals(v)) { webView.callHandler("functionInJs", "data from Java", new CallBackFunction() {@Overridepublic void onCallBack(String data) {// TODO Auto-generated method stubLog.i(TAG, "reponse data from js " + data);}});}}}2 自定webVIewClient
class MyWebViewClient extends BridgeWebViewClient{ public MyWebViewClient(BridgeWebView webView) { super(webView); } }
mWebView.setWebViewClient(new MyWebViewClient(mWebView));
上面句话很关键:
//必须和js函数同名,注册具体执行回调函数,类似java实现类。webView.registerHandler("submitFromWeb", new BridgeHandler() {@Overridepublic void handler(String data, CallBackFunction function) {String str ="这是html返回给java的数据:" + data;// 例如你可以对原始数据进行处理makeText(MainActivity.this, str, LENGTH_SHORT).show();Log.i(TAG, "handler = submitFromWeb, data from web = " + data); function.onCallBack( str + ",Java经过处理后截取了一部分:"+ str.substring(0,5));}});
如果是webview刚开始就执行一段Java代码 ,可以通过webView.CallHandler()来实现 。当然我们注册的方法也要和js里面的方法名一致。
webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) {makeText(MainActivity.this, "网页在获取你的位置", LENGTH_SHORT).show(); } });
3 Html和js实现
html代码如下,效果图
<html> <head> <meta content="text/html; charset=utf-8" http-equiv="content-type"> <title> js调用java </title> </head> <body> <p> <xmp id="show"> </xmp> </p> <p> <xmp id="init"> </xmp> </p> <p> <input type="text" id="text1" value="用户名(username)" /> </p> <p> <input type="text" id="text2" value="password" /> </p> <p> <input type="button" id="enter" value="发消息给Native" onclick="testClick();" /> </p> <p> <input type="button" id="enter1" value="调用Native方法" onclick="testClick1();" /> </p> <p> <input type="button" id="enter2" value="显示html" onclick="testDiv();" /> </p> <p> <input type="file" value="打开文件" /> </p> </body> </html>
js代码
<script> function testDiv() { document.getElementById("show").innerHTML = document.getElementsByTagName("html")[0].innerHTML; } function testClick() { var str1 = document.getElementById("text1").value; var str2 = document.getElementById("text2").value; //发送消息给java代码 var data = "name=" + str1 + ",pass=" + str2; window.WebViewJavascriptBridge.send( data , function(responseData) { document.getElementById("show").innerHTML = "repsonseData from java, data = " +responseData } ); } function testClick1() { var str1 = document.getElementById("text1").value; var str2 = document.getElementById("text2").value; //调用本地java方法 window.WebViewJavascriptBridge.callHandler( 'submitFromWeb' , {'param': str1} , function(responseData) { document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData } ); } function bridgeLog(logContent) { document.getElementById("show").innerHTML = logContent; }//注册事件监听 function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener( 'WebViewJavascriptBridgeReady' , function() { callback(WebViewJavascriptBridge) }, false ); } } //注册回调函数,第一次连接时调用 初始化函数 connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); var data = { 'Javascript Responds': 'Wee!' }; console.log('JS responding with', data); responseCallback(data); }); bridge.registerHandler("functionInJs", function(data, responseCallback) { document.getElementById("show").innerHTML = ("data from Java: = " + data); var responseData = "Javascript Says Right back aka!"; responseCallback(responseData); }); }) </script>
这段代码不难理解,我们对上面的id为enter的Button注册了一个点击事件,点击后执行以下testClick()方法,依次类推,其他Button注册事件相同,
当点击“发消息给Native”的按钮时,Js通过webWiew的jsBridage.send()发送一条数据给java层(密码和用户名),同时在此用function()来执行应java层回调函数的。此demo中是把java返回的数据插入到"show"的div里面去。
testClick1():此方法中调用callHandler来调用Java代码的submitFromweb同名函数,可以结合上面的Activty的代码理解下,此函数调用我们已在java注册实现好的
//必须和js同名函数,注册具体执行函数,类似java实现类。webView.registerHandler("submitFromWeb", new BridgeHandler() {@Overridepublic void handler(String data, CallBackFunction function) {String str ="这是html返回给java的数据:" + data;// 例如你可以对原始数据进行处理makeText(MainActivity.this, str, LENGTH_SHORT).show();Log.i(TAG, "handler = submitFromWeb, data from web = " + data); function.onCallBack( str + ",Java经过处理后截取了一部分:"+ str.substring(0,5));}});
java注册Js函数如上面列子 ,那么在js中注册方法来注册呢,
在js中我们同样可以直接注册一个回调函数,通过 bridge.registerHandler()来注册,接着调用 responseCallback(responseData)来返回数据给java代码的同名函数。f
也可以直接调用init()来指定网页首次加载上面注册java代码。
connectWebViewJavascriptBridge(function(bridge) { bridge.init(function(message, responseCallback) { console.log('JS got a message', message); var data = { 'Javascript Responds': 'Wee!' }; console.log('JS responding with', data); responseCallback(data); }); bridge.registerHandler("functionInJs", function(data, responseCallback) { document.getElementById("show").innerHTML = ("data from Java: = " + data); var responseData = "Javascript Says Right back aka!"; responseCallback(responseData); }); })
四 总结
- Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
- Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
- Android 利用WebViewJavascriptBridge 实现js和java的交互(一),androidjsbridge
- Android 中利用WebViewJavascriptBridge 实现js和java的交互
- Android 利用WebViewJavascriptBridge 实现js和java的交互
- Android 利用WebViewJavascriptBridge 实现js和java的交互
- Android 中利用WebViewJavascriptBridge 实现js和java的交互
- Android 利用WebViewJavascriptBridge 实现js和java的交互
- Android 利用WebViewJavascriptBridge 实现js和java的交互
- WebViewJavascriptBridge 实现js和java的交互
- Android中WebViewJavascriptBridge实现JS与java安全交互
- WebViewJavascriptBridge源码探究--看OC和JS交互过程(介绍了WebViewJavascriptBridge的实现过程)
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
- iOS OC与JS的交互(WebViewJavascriptBridge实现)
- 通过WebViewJavascriptBridge实现OC与JS交互
- 使用WebViewJavascriptBridge实现OC与JS交互
- 使用WebViewJavascriptBridge实现OC与JS交互
- 使用Android Studio分析内存问题
- 用纯CSS实现的箭头
- DispatcherServlet详解
- hdu 1569 方格取数2(网络流最小割)
- 快速排序
- Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
- java中,continue的使用。
- 在mysql安装后临时密码后不能登录更换
- Servlet中<url-pattern>匹配
- taskctl新增作业类型配置插件时注意事项
- vmvare12安装rehat6.4,并激活网卡
- css小图标
- vueJS的双向绑定原理
- Islands in the Data Stream UVALive