November 3, 2015

SwiftlyHybrid and AndyHybrid

Posted in Uncategorized at 8:28 pm by tetontech

In several of my previous posts over the last seven years I’ve described how to use web views with HTML5, CSS3, and JavaScript to develop installable apps for both iOS and Android. The earliest examples lead to the creation of QuickConnect (QC) and influenced the development of its first competitor, PhoneGap/Cordova. Those tools and others like them included extensive ‘bridging code’ to enable calls to Objective-C or Java and then back to JavaScript so the weaknesses of the older versions of the web views could be overcome.

As the iOS and Android web views’ capabilities have grown, the need to augment them with additional native iOS and Android code has decreased. Now audio and video can be recorded and played within the web views. Pictures can be taken and voices can be used to read text. Data can be easily stored and retrieved from local and remote stores. Nearly all of the functionality developers now need is encapsulated in the web views. Because of the continual growth of HTML5, CSS3, JavaScript, and web view support for them, heavy and complicated tools like QC and PhoneGap/Cordova are no longer needed. Instead much lighter and more standardized tools can be used. I’ve created SwiftlyHybrid and AndyHybrid to show what can be done. You’ll find each of them in their gitHub repositories. They are MIT licensed so feel free to do anything you like with them. SwiftlyHybrid has iOS and OS X example projects and AndyHybrid includes an Android Studio example project.

SwiftlyHybrid uses Apple’s WKWebView and the Swift programming language. AndyHybrid uses Google’s WebView that ships with Lollipop and Marshmallow. (Google claims this version of WebView will degrade gracefully when running on older Android OS versions.) Over time, the API’s for these two web views and their HTML5, CSS3, and JavaScript support have been converging. This means it is easier to write hybrid apps than ever before.

For both SwiftlyHybrid and AndyHybrid nearly all applications will only need to replace the HTML, CSS, and JavaScript files with custom ones and be done. For those few apps that still need to do something not possible in the web views’ sandbox I’ve created a standardized way to call from JavaScript to Swift or Android and get results back. HTML5 support and this bridge help SwiftlyHybrid and AndyHybrid use less RAM and CPU than the older QC and PhoneGap/Cordova tools, yet they are less complicated, and just as capable.

If you want to make calls down to Swift for iOS or Java for Android using one or both of these tools, the JavaScript code is the same. Here is a silly example that works for Both SwiftlyHybrid and AndyHybrid. In the example a message is put together and then past to the native code using the postMessage method.

var clicks = 0
function sendCount(){
    
    var message = {"cmd":"increment","count":clicks,
                           "callbackFunc":function(responseAsJSON){
        var response = JSON.parse(responseAsJSON)
        clicks = response['count']
        document.querySelector("#messages_from_java").innerText = 
                                                  "Count is "+clicks
    }.toString()}
    native.postMessage(message)
}

The message is a JavaScript associative array. it contains the command “increment” and some data, the current value of the “clicks” variable, and a callback function. Calling the postMessage function provided by both SwiftlyHybrid and AndyHybrid will convert the message associative array into JSON and send it to the native code portion of your app. In order for the callback function to be passed, it must be converted to a string otherwise the JSON library will strip it out. Since this message isn’t going across the internet or an internal network we don’t have to worry about XSS attacks so executing the string in the native code as JavaScript isn’t a security issue.

The Swift code for handling the message is in the SwiftlyMessageHandler.swift file in the SwiftlyHybrid example. It looks like this:

let command = sentData["cmd"] as! String
        var response = Dictionary<String,AnyObject>()
        if command == "increment"{
            guard var count = sentData["count"] as? Int else{
                return
            }
            count++
            response["count"] = count
        }
        let callbackString = sentData["callbackFunc"] as? String
        sendResponse(response, callback: callbackString)

The current count is first pulled from the data sent from JavaScript. It is incremented and then SwiftlyHybrid’s sendResponse method is used to execute the callback JavaScript function using the response dictionary as a parameter to the JavaScript callback function.

The Java code for AndyHybrid is very similar. It is in the JavaScriptCommunication.java file.

HashMap<String, Object> message = (HashMap) JSONUtilities.parse(aMessageAsJSON);
String command = (String)message.get("cmd");
Serializable response = null;
if(command.equals("increment")){
       long count = (long)message.get("count");
       count++;
       HashMap<String,Object> dataMap = new HashMap<>();
       dataMap.put("count",count);
       response = dataMap;
}
String asyncCallback = (String) message.get("callbackFunc");
sendResponse(response, asyncCallback);

In both languages the command is retrieved from the associative array generated from the JSON message string, the count is also retrieved and incremented, a response is created containing the updated count, and the response is passed to the callback JavaScript function. The callback, in both cases, is executed within the web view and in the web view’s thread.

Having shown you the JavaScript, Swift, and Android Java to do communication between the two ‘layers’ of hybrid apps, I must say again, seldom is this type of inter-thread communication needed. Most of what you will want to do can be done directly in JavaScript, HTML, and CSS.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: