Yixin Toumi RA | Android Cross-platform Development Practice


At present, the mainstream platforms on the mobile market mainly include Android and IOS. In order to reuse code and save development costs as much as possible, each major giant has developed its own cross-platform framework, such as Facebook’s React-Native, Ali’s Weex, Cordova, and Flutter framework introduced at this year’s Google Developer Conference. These frameworks have their own advantages and disadvantages, but so far they have not been widely popularized. In my opinion, there are mainly the following reasons:

1. The developer ecosystem is not mature enough. RN is the most concerned and ecologically active framework of the three major cross-platform frameworks, but so far there is no version 1.0 (the latest release is 0.57.8), not to mention Weex and Flutter of the latter. Ecological immaturity means that there are fewer development documents and fewer open source controls that can be used. For example, it is difficult to do a basic pull-down refresh and pull-up to load more listview on RN. Weex has contributed to Apache and has not updated release for a long time. Flutter is still in beta and its development remains to be seen.

2. Performance issues. Although these frameworks have optimized rendering performance, they are still worse than the original ones. RN and weex have implemented a browser jsCore themselves, so rendering will be slower with an extra layer of JS parsing. For example, if the listview of RN has too much data, Caton will appear. Flutter has its own rendering engine, but it is still some distance from the original.

3. Compatibility problem. Although the original intention of the three platforms is to cross-platform (Write/Learn once, run everywhere), a lot of energy is still needed to compatibility and adaptation in practical application. For example, RN’s performance on Android low-end machines is not satisfactory. Even Airbnb, a strong supporter of RN, has announced to give up using RN.

4. Cost of development and integration. The three frameworks need to learn new languages React, vue, dart and weex. The biggest advantage is that the introduction is simple. However, the version iteration is slow, RN has a high starting threshold, and development and debugging are difficult. Many so files will be added to the integrated RN and weex frameworks, increasing the installation package size by at least about 10M, which does not include the third-party library. Flutter has just come out and has not been applied much, and its effect remains to be observed. However, cross-platform mobile development is the general trend, which can save development costs, improve development efficiency and respond to business changes quickly. Currently, mainstream applications still use H5 and native communication to realize cross-platform development.

Android and IOS platforms both have their own built-in browser kernel webkit framework. The essence of cross-platform is that codes written with H5/JS can be run in WebView of Android and IOS respectively, thus realizing the purpose that one code can run on both platforms.

The communication between Native and JS on Android platform is mainly realized by WebViewClient and WebChromeClient. WebViewClient is used to help WebView handle various notifications and event requests. Its main methods are: onLoadResource, onPageStart, onPageFinished, onReceiveError, ShouldOVERRIDEULLOAD, etc.

WebChromeClient handles event responses of JS pages, such as dialog boxes, icon, title and loading progress of web pages. The corresponding response methods are OnJSAlert, OnJSConfirm, OnJSConsole, OnProgressive, OnReceiveIcon, OnReceiveTitle, etc.

To realize Java and JS communication, it is necessary to:

1. Resolve Java tuning JS; 2, JS tunes Java.

Java calls JS through loadUrl and evaluateJavaScript. Through WebView. loadUrl (“JavaScript: Alert (‘Hello World’)”), js code can be injected into html pages on android platform. LoadURL method can directly call functions defined in js, or js files in the assets directory local to android can be injected into html pages in the form of strings. However, this injection timing cannot be done until the html page is loaded, that is, it is called in the callback function of WebViewClient.onPageFinished, which is equivalent to directly referencing js resource files in the html page.

For the client, java calling js is essentially a process of splicing js strings, but calling loadUrl cannot directly obtain the return value of js function. After Java calls js function, you can get the return value of js function. webview.evaluateJavaScript method can be used, but this method can only be used in android4.4 version 4.4 and above. Other usage is consistent with loadUrl.

JS calls Java can be divided into three types: 1. Object mapping; 2. URL interception; 3. JS method intercept.

The object mapping is through WebView. AddJavaScriptInterface (New jsObject (), “javaObject”), so that the JavaObject object can be directly called in JS code, thus realizing the function of JS calling Java. However, this method has security vulnerabilities under android4.2. Using reflection mechanism to call Android API getRuntime to execute shell commands to attack, such as traversing sdcard, sending short messages, installing trojan horse APK, etc.

URL interception refers to the four methods of iframe.src, window.open, documention.location or href that can open a connection in an html page, thus triggering the webviewclient.shouldoverrideurlloading method in Java. For example in js
The Data transmitted from JS can be obtained according to the agreed protocol format and protocol name (Authority) in shouldOverrrideUrlLoading.

Calling alert, console, prompt, confirm and other methods in JS will trigger callback of onJsAlert, onConsoleMessage, onJsPrompt, onJsConfirm methods of WebChromeClient. For example, it can be called in js
The contents of prompt can be obtained in message of onJsPrompt, and then the data can be obtained according to the agreed protocol format.

In order to solve the communication problem between JS and Native, a JSBridge framework (https://github.com/lzyzsd/JsB …) Used to be responsible for communication between H5 and Java. Problems to be solved:

1. How JS callbacks each other after Java calls to pass responseData back;

2. JS calls Java in three ways. If you choose which method is more appropriate.

For question 1, a data structure can be defined on java and js sides: message = {callback id: XXX, handlename: XXX, responsedata: XXX, responseid: XXX}. Save the callback function in callbackId. When JS or Java finishes processing the data callback, the callback function saved in callbackId is stored in responseId, and the corresponding callback data is stored in responseData, so as to respond to the callback message after JS or Java calls.

Although there are three methods for Js to call Java, it is generally not recommended to use addJavaScriptInterface due to security problems. The alert and console methods in JS are commonly used in Html pages. Although confirm and prompt are not commonly used, dialog boxes will pop up in some mobile phone system versions, which is not common. Therefore, a better choice is url interception, which can trigger shouldOverrideUrlLoading through iframe.src.

The use of JsBridge framework is mainly divided into:

1, injecting a local js file after the H5 page is loaded;

2. Registering BridgeHandler in Java code to process messages sent by JS;

3. Define _handleMessageFromNative in the locally injected js file to receive the message passed by java;

4. Because the js injected by the client is asynchronous, it is necessary to register the Event Listener in the js file and notify H5 after success.

Native calls JS, e.g. via webview.loadurl (“javascript: webviewjavasscriptbridge. _ handlemagefromnative (‘{“callback id “:”java _ cb _ 2 _ 559 “,”data “:”justdatafrom java “}’)));

In this way, js’s handleMessageFromNative method can be called. The data format passed is Message and callBackId to respond to js’s callback, which will be stored in HashMap before sending. js finds the corresponding callback function to process JS’s response data according to JAVA_CB_2_559 during callback. The specific process is as follows:

Js calls Java and converts the passed information into Message = {Data: {…}, callbackId: “CB _ 1 _ 1234”} where Callback ID is js’s callback function.

Then, through iframe.src =’ YY://return/_ fetch queue/[{“data”: “xxxx”, “callback id”: “CB _ 1 _ 4321”}] “,the shouldOverrideUrlLoading method is triggered. after java processes the data transferred from js, Set callback function cb_1_4321 to message = {responseid: CB _ 1 _ 4321, responsedata: XXX} so that callback functions can be processed in js.

The specific flow chart is as follows:

JsBridge framework provides two handler methods. registerHandler methods need to pass in the name of Handler, which requires IOS, Android and H5 to agree on the name, because the business requirements developed by H5 change rapidly, and H5 calls native methods randomly. Therefore, it is not convenient to extend these handler method names by using the registerHandler convention name every time. Therefore, in actual development, when using defaultHanlder, H5 calls the native method, it is required to use a cmd, that is, the convention Data = {cmd: XXX, Time: Data: {…}}. As long as there is corresponding function to CMD command in the native code, the H5 page can call the native method at any time.

JsBridge’s improvement suggests that java calls to js will occasionally fail because webview calls to JS methods must take effect on the main thread.

In addition, Js calls to Java occasionally fail because the iframe mechanism cannot guarantee that the shouldOverrideUrlLoading callback can be triggered every time.

At present JSBridge adopts url scheme. if Android4.2 or below and IOS7 or below are not considered, interactions can be adopted, such as directly injecting a Native object into JS page using addJavaScriptInterface, and changing the previous triggering u step into sending a message to Native using this Native object. This method is only a feasible scheme, and the current JSBridge scheme basically meets the business requirements in actual use.

Author: bregYixin Institute of Technology