Android uses WebViewJavascriptBridge to achieve interaction between js and java (1). androidjsbridge
This article from: http://blog.csdn.net/sk719887916/article/details/47189607, skay blog
According to the current situation of Android development, developers spend most of their time on UI screen adaptation, and the development cost of using native controls is not that ideal. Considering that many projects and ios are based on consistent ui interfaces, android UI development costs are much higher. Therefore, combining Html5 with native controls is a good choice for UI adaptation, java and native layers are also used for APP performance. Whatever the combination, the principle is almost the same. It is very easy to follow the protocol. Today we only use the combination of Html and Java layers to learn the next open-source project-WebViewJavascriptBridge.
1. What is webViewjavascripBridge?
WebViewJavascriptBridge is a bridge between mobile UIView and Html interactive communication. In the author's words, it is a bridge between java (ios is oc) and js calls. It replaces the built-in JavascriptInterface interface of WebView, making our development more flexible and secure.
2. Why webViewjavascripBridge? For Android Developers for some time, they know that Google's webview had a security vulnerability before Android 4.4, and the website can get important information from the client through js injection, it is even easy to call local code for rogue behavior. After Google finds this vulnerability, it adds defense measures. If JavaScript calls local code, developers must declare JavascriptInterface in the code, before column listing 4.0, we only need the following code to make webView load js:
mWebView.addJavascriptInterface(new JsToJava(), "myjsfunction");
After 4.4, add the @ JavascriptInterface annotation to the call method. If the Code does not have this Declaration, js cannot take effect, that is to say, this can prevent malicious web pages from using js to steal and attack Android clients.
However, in this case, we often need to make some judgments and restrictions when recording local code in js, or we may also do some filtering and user friendly prompts, therefore, JavascriptInterface cannot meet our needs. Therefore, we have written the WebViewJavascriptBridge framework.
3. How to Use webViewjavascripBridge 1 to introduce jsBridge. jar to our project. The jar or jar source code can be downloaded on gitHub.
2. The WebView package must use the webView of the preceding package.
Use a third-party view in Layout. For example:
<? 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 demonstrates Java calling web --> <Button android: id = "@ + id/button" android: layout_width = "match_parent" android: text = "@ string/button_name" android: layout_height = "48dp"/> <! -- Webview demo web call 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 code
Public class MainActivity extends Activity implements OnClickListener {private final String TAG = "MainActivity"; BridgeWebView webView; Button 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 (savedInsta NceState); 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) {th Is. openFileChooser (uploadMsg);} @ SuppressWarnings ("unused") public void openFileChooser (ValueCallback <Uri> uploadMsg, String AcceptType) {this. openFileChooser (uploadMsg);} public void openFileChooser (ValueCallback <Uri> uploadMsg) {mUploadMessage = uploadMsg; pickFile () ;}); // load the local webpage // webView. loadUrl ("file: // android_asset/demo.html"); // load the webView of the server webpage. loadUrl ("https://www.baidu.com"); // must be a function with the same name as js, register the specific execution letter Similar to java Implementation class. WebView. registerHandler ("submitFromWeb", new BridgeHandler () {@ Overridepublic void handler (String data, CallBackFunction function) {String str = "this is the data html returns to java:" + data; // For example, you can process the original data makeText (MainActivity. this, str, LENGTH_SHORT ). show (); Log. I (TAG, "handler = submitFromWeb, data from web =" + data); function. onCallBack (str + ", Java is intercepted after processing:" + str. substring () ;}}); // simulate the User to obtain the local user = New User (); Location location = new Location (); location. address = "Shanghai"; user. location = location; user. name = "Bruce"; webView. callHandler ("functionInJs", new Gson (). toJson (user), new CallBackFunction () {@ Override public void onCallBack (String data) {makeText (MainActivity. this, "the webpage is retrieving your location", LENGTH_SHORT ). show () ;}}); webView. send ("hello");} public void pickFile () {Intent chooserIntent = new In Tent (Intent. ACTION_GET_CONTENT); chooserIntent. setType ("image/*"); startActivityForResult (chooserIntent, RESULT_CODE);} @ effecvoid 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. onuploevalue (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 );}});}}}
By instantiating webView, the usage is no different from that of Android native view. You can set WebChromClient and html to be loaded (network and local files are also supported ), next, we need to register the js method name agreed upon by the web and html end. Code list
SubmitFromwebIt is the same as the method name for js execution. Friends who have played NDK's JNI call also know that there must be an agreement with c code. In fact, js bridge and jni are a bit similar,
Callback is implemented by registering handler. The data returned by js in Java code is processed and then returned to js by calling function. onCallback. This will not be explained too much here.
// It must be a function with the same name as js and register a specific execution function, similar to the java Implementation class. WebView. registerHandler ("submitFromWeb", new BridgeHandler () {@ Overridepublic void handler (String data, CallBackFunction function) {String str = "this is the data html returns to java:" + data; // For example, you can process the original data makeText (MainActivity. this, str, LENGTH_SHORT ). show (); Log. I (TAG, "handler = submitFromWeb, data from web =" + data); function. onCallBack (str + ", Java is intercepted after processing:" + str. substring ));}});
If webview executes a piece of Java code at the beginning, it can be implemented through webView. CallHandler. Of course, the method we register must be the same as the method name in js.
WebView. callHandler ("functionInJs", new Gson (). toJson (user), new CallBackFunction () {@ Override public void onCallBack (String data) {makeText (MainActivity. this, "the webpage is retrieving your location", LENGTH_SHORT ). show ();}});
3 Html and js implement the following html code,
<Html>
Js Code
<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; // send a message to the java code var data = "name =" + str1 + ", pass =" + str2; window. webViewJavascriptBridge. send (data, function (responseData) {document. getElementB YId ("show "). innerHTML = "repsonseData from java, data =" + responseData});} function testClick1 () {var str1 = document. getElementById ("text1 "). value; var str2 = document. getElementById ("text2 "). value; // call the local java method 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;} // register the event listening function connectWebViewJavascriptBridge (callback) {if (window. webViewJavascriptBridge) {callback (WebViewJavascriptBridge)} else {document. addEventListener ('webviewjavascriptbridgeready', function () {callback (WebViewJavascriptBridge)}, false) ;}// registers the callback function and initializes the function. 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>
This code is not hard to understand. We have registered a click event for the Button with the id "enter", and then run the following testClick () method, and so on. The registration events of other buttons are the same,
When you click "send message to Native", Js uses jsBridage of webWiew. send () sends a piece of data to the java layer (password and user name), and uses function () to execute the java-layer callback function. In this demo, the data returned by java is inserted into the "show" div.
TestClick1 (): Call callHandler in this method to call the Java codeSubmitFromwebFunctions with the same name can be understood in combination with the above Activty code. We have registered and implemented this function in java.
// It must be a function with the same name as js and register a specific execution function, similar to the java Implementation class. WebView. registerHandler ("submitFromWeb", new BridgeHandler () {@ Overridepublic void handler (String data, CallBackFunction function) {String str = "this is the data html returns to java:" + data; // For example, you can process the original data makeText (MainActivity. this, str, LENGTH_SHORT ). show (); Log. I (TAG, "handler = submitFromWeb, data from web =" + data); function. onCallBack (str + ", Java is intercepted after processing:" + str. substring ));}});
Java registers Js functions as shown in the preceding column. How can I register them in js,
In js, we can also directly register a callback function, register it through bridge. registerHandler (), and then call responseCallback (responseData) to return data to a function with the same name as the java code. F
You can also directly call init () to specify the first time the webpage loads the registered java code above.
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); }); })
Conclusion 4 through the above code examples, it is not difficult to find that the framework is elegant and simple. For js and java, if Javascript in html needs to call java code, and java code has not been implemented, this js is also invalid. If the callback function registered by java code is not implemented in js, Java cannot obtain js remote data. Therefore, this communication is implemented by both parties, the dual-release Protocol is required, which avoids the js injection vulnerability in Android and greatly improves security. It also ensures that our webpage data is not obtained by third-party apps, for example, if an html interface of your project is maliciously loaded to your website or webpage by an android browser or another third-party App, its java code calls your js function, for example, if your JavaScript code is registered or implemented in advance, it cannot be called in the future. This ensures the uniqueness of this html. A third party can load and preview your webpage, but the third-party java cannot communicate with your js. When loading third-party web pages, we can filter the behaviors of third-party web pages to provide user friendly prompts. The above code is only part of the functions of this open-source framework. There are still many functions that need to be explored. We will reveal the internal implementation of this open-source project. Read
Open Source Address: https://github.com/lzyzsd/JsBridge
Copyright Disclaimer: This article is the original article of the blogger. Please respect the original article and indicate the address for reprinting.