WebViews and HTML5 Containers

Intro

Until recently, web applications were restricted to browsers. Now, they can run on mobile devices (in a webview) and on the desktop (in an HTML5 container). The proliferation of mobile devices, the release of the Chromium Embedded Framework, and the emergence of Electron have all contributed to the widespread use of web technologies outside of a typical web browser.

The ChartIQ library can operate in any of these environments. All of the guidance and tutorials provided by our documentation applies, regardless of whether you're developing your application for browsers, mobile devices or desktop containers. This tutorial will:

  • Introduce you to webviews and containers
  • Discuss issues related to working with webviews/containers.
  • Recommend resources for further reading.

First, let's clear up some terminology.

Webview vs Container

Webview: At the most basic level, a webview is simply a UI-less browser window configured to run in full screen. It's just a frame that delivers web content.

Container: A container is a platform that embeds Chromium into a native shell. The container allows a developer to build native apps without C++ or Java.

For simplicity, we will use webview at times to reference both environments.

Communicating with WebViews and Containers

You will probably need to communicate between your webview and the native code that it's running within. Consider the case where you'd like to put charts into your existing native mobile application. If all that's required is a chart that displays up to date data, the task is simple. But as soon as you introduce UI that alters the chart state, you will need to pass instructions from the native app to the embedded webview; the webview may also need to communicate back to the native application when its state changes. The example below shows how to use a native iOS button to trigger a chart type change inside of a webview:

-(IBAction)toggleHollowCandle:(id)sender {
//javascript function in the webview called setChartType
NSString *func =@"setChartType('hollow_candle');";
//code below calls the function inside of our webview
[_webView evaluateJavaScript:func completionHandler:^(id Result, NSError * error) {
        NSLog(@"Error -> %@", error);
    }];
}

Sidebar: Advantages of Remote Deployment

When designing your application's architecture, you will need to decide how to manage its assets (files). You can either host them on a server, or bundle them with the application itself. While there are valid reasons to bundle your assets with your application, we believe that the pros of remote hosting generally outweigh the cons. Some of the benefits of remote hosting are:

  • Upgrading our library becomes trivial. If the library is packaged with your application, you will need to release a new version before the library license expires. If your users don't upgrade their application, they could be stuck with an expired version of the library. If the library is hosted on your server, you simply need to swap out the files for your users to automatically be upgraded.
  • Because it's so easy to swap out files on a server, the application can be upgraded as frequently as necessary. Shorter release cycles allow for incremental improvement; which in turn leads to less user confusion.

Special considerations when working with webviews/containers

Now that you know what webviews and containers are and how to communicate with them, let's talk about some of the things you need to consider when deploying an application inside of one.

ChartIQ Licensing for native apps

Trial versions of the ChartIQ library are mobile ready and will run on any mobile OS even if bundled with the application itself. So will the production versions when hosted remotely on a server. If you are planning on bundling the library with your application, please let us know so we can send you a suitable package. The standard domain locked library will not work in this case. See 'Sidebar: Advantages of Remote Deployment' for details on these 2 approaches.

iOS Quirks

iOS WebViews do not automatically follow relative paths. You'll need to ensure that your files can be found by iOS. For more information about relative paths in iOS apps, see this tutorial. Or search for 'Add files and folders to a project' in the Apple xcode help site

Android Proguard Rules

You should be careful not to use proguard rules that may modify the library code in ways not intended. That will cause it to malfunction. If when enabling proguard rules your application stops working, disable them and review this article to create an optimal configuration for your needs: Making a Release Build

Debugging

You won't have a dev console immediately available. Debugging code running in webviews and containers requires special considering. For more information on remote debugging, check out our debugging tutorial.

OS Localization vs. WebViews Localization

The charting library does not automatically check the OS localization settings. If this is necessary in your app, you must explicitly create a method to sync up the OS and the WebView on initial load and every time a change is made on the OS side so they stay in sync. See Localization for more details.

Synchronous and asynchronous code

JavaScript is an asynchronous language. This means that it only has a single thread of execution and handles concurrency through events. In contrast, native languages such as Objective-C and Java are synchronous. They handle concurrency using threads. Improper implementation of native <--> JavaScript communication can result in bugs or UI problems.

There are infrequently any problems with native code that calls a JavaScript function. The JavaScript will finish executing and return control back to the native application. More consideration is necessary when JavaScript calls out to a native method. The JavaScript code, and thus the WebView, will be hung until the native code responds. Therefore it is essential that native code that handles JS requests returns immediately. Generally this means that the native code which makes network requests should spin up a new thread, keeping track of the JavaScript context and returning the data at a later point.

Here is sample code for creating a native to JS bridge:

// This will save context so that the native application can return data to JavaScript without hanging the user interface
CIQ.asynchronizer = function(cb) {
	var unique = CIQ.uniqueID();
	window[unique] = function() {
		cb.apply(this, arguments);
		delete window[unique];
	};
	return unique;
};

// Fetch some data from the native interface
function fetchData(key, cb) {
	var self = this;
	function response(err, json) {
		if (err != "") cb(err);
		else {
			cb(json);
		}
	}

	// nativeInterface will depend on the operating system. Your native code should spin up a new thread. The second parameter will contain a "handle" that we will use to return the data via the cb.
	nativeInterface.fetchData(key, CIQ.asynchronizer(response));
}

// When your native code has data, call this JS function.
CIQ.asynchronizerResult = function(unique, err, data) {
	window[unique](err, data);
};

Managing sliding and swiping:

Sometimes the chart will be embedded in a larger page that can be swiped up or down. To decide if you want the chart to respond to the swiping or let the page manage it, see the following settings:

Performance

Resources

Recommended Webviews/Containers

iOS provides two webviews - UIWebView, and WKWebView. WKWebView is based on WebKit, the same rendering engine that powers Safari and Chromium. We recommend using wkWebview because it includes just in time (JIT) compiling and therefore performs much better than the older UIWebView.

For building Android apps, although as of Android 5.0 (Lollipop) the WebView has moved to an APK so it can be updated separately, you may want to use the Intel Crosswalk SDK. Crosswalk automatically bundles the latest Chromium build which improves performance on Android devices prior to version 4.4. Note that Crosswalk is currently unmaintained.

Here are some useful links:


Next Steps: