Tag Archives: hybrid

JavaScript All The Things – Or – Why You Should Pay Attention To JavaScript

This post is inspired by all the comments I’ve seen this week about JS in the enterprise. I would have never imagined this 10 years ago, but JavaScript is now pretty much ubiquitous. Here are a few reasons why you need to paying attention to JavaScript if you aren’t already, and why you should definitely not write it off.

First, I think one of the major reasons for JavaScript’s ubiquity is that JavaScript is approachable. It is relatively easy for beginners to learn JavaScript, and powerful enough for advanced users to build complex and reliable systems.

Second, why you need to pay attention, JavaScript is everywhere.

jsatt

You can now use JavaScript to develop on virtually any platform: client side applications, server side logic, embedded chips/IoT devices, manage build scripts and dependencies, and more.

This doesn’t mean you’ll use the exact same code in every case, rather that you can use the same skill set – JavaScript Development – to deliver solutions across multiple paradigms.

The Client Side

JavaScript can be used to power client side apps/user interfaces, and user interactions on numerous platforms and devices.

Web

Of course JavaScript powers the web, this is a given. JavaScript is the primary scripting language for all web browsers. I won’t focus on this much b/c it’s already well known.

Mobile

JavaScript can also be used to power mobile applications that are natively installed on a device.

  1. Apache Cordova/PhoneGap – You can build natively installed apps with web technology using PhoneGap or Cordova. PhoneGap is Adobe’s branded distribution of Cordova, but from the developer’s perspective, they are basically the same thing. Your app runs within a webview on the mobile device, and you build your user interface the same way you you build a dynamic web application. Your user interface is implemented in HTML, styled with CSS, and all interactivity is created with JavaScript.
  2. React Native – JavaScript powered web apps don’t just have to be inside of a a web view. The React Native framework gives developers the ability to write their application using JavaScript and declarative UI elements, and results in a native application running on the mobile device. The logic is interpreted JavaScript at runtime, but everything that the user interacts with (all UI elements) is 100% native, providing a very high quality user experience, and it is now available for both iOS and Android applications.
  3. Unity 3D – You can even develop rich & immersive mobile 3D simulation or gaming experience, entirely powered by JavaScript using the Unity 3D engine. **These can be web, desktop, or mobile, but is often used in mobile gaming.
  4. NativeScript – Framework for building cross-platform native iOS, Android and Windows mobile apps using JavaScript.
Desktop

Yup, desktop apps are not left out of the mix. Most desktop solutions fall into a category similar to Apache Cordova, where the end results is a web view that has access to lower level APIs, whose content is developed with web based technology.

  1. Electron – Node.js + Chromium desktop app container from GitHub
  2. app.js  – Node + Chromium for a desktop app container
  3. nw.js – Another framework for Node +Chromium for a desktop app container
  4. CEF – The Chromium Embedded Framework – a framework for embedding the guts of the chrome browser inside of a desktop app.

… and more… I know Microsoft has a solution for building Windows apps purely out of HTML/JS, and there are more solutions out there that I am forgetting.

In fact, some of my favorite desktop tools, such as SlackAtom and VS Code are actually based on web technology and implemented in HTML/JS. Heck, even Photoshop can be scripted and extended with the generator extensibility layer or have a customized user interface in HTML/JS with design spaces.

The Server Side

Most obviously Node.js – a JavaScript runtime buit on Chrome’s V8 JavaScript Engine – has made huge inroads into server side development and the enterprise. Node.js, powered by frameworks like express.js or loopback.io makes server side development and complex enterprise apps with JavaScript possible.

IoT

Pretty much everything that doesn’t fall in the categories above falls in here. You can develop headless apps that run on Arduino, Raspberry Pi or other small boards completely using JavaScript, you can manage infrastructure and information flow of IoT sensors using JavaScript, you can write on-chip programs for embedded systems using JavaScript, you can control robots with it, and you can even power media-centric connected TV experiences using JavaScript.

Like I said… It’s everywhere.

Ecosystem

It’s not just about where you can build and run JavaScript for your applications. JavaScript has a massive and thriving developer ecosystem.

JavaScript is the #1 most active language on GitHub in both the total number of active repositories and total number of active pushes/commits.

 

http://githut.info/
statistics visualization from http://githut.info/

Here are some stats that show the magnitude of growth and adoption for Node.js/npm.js alone. NPM stats currently shows a total of 186,946 packages available for download, 94,978,032 package downloads in the last day, and 2,451,734,737 package downloads in the last month.

npm
NPM Statistics

 

Node.js adoption is massive, and is still growing.

This doesn’t mean that JavaScript is the best language at everything. It also doesn’t meant that you can take a single piece of source code and run it in every device/context imaginable.

It means that you can use your skills in JavaScript to develop for just about any kind of device/context out there. It’s not going to be write once, run everywhere, rather in the words of the React.js team: learn once, write everywhere.

Data Management for Apps that Work as Well Offline as They Do Online

Earlier this week I had the privilege of speaking at ApacheCon in Austin, TX on the topic of data management for apps that work as well offline as they do online.  This is an important topic for mobile apps, since, as we all painfully know already, there is never a case when you are always online on your mobile devices.  There always ends up being a time when you need your device/app, but you can’t get online to get the information you need.  Well, this doesn’t always have to be the case. There are strategies you can employ to build apps that work just as well offline as they do online, and the strategy I’d like to highlight today is based upon data management using the IBM Cloudant NoSQL database as a service, which is based upon Apache CouchDB.

Here’s a link to the presentation slides (built using reveal.js) – just use the space bar to advance the presentation slides:

The “couch” in CouchDB is actually an acronym for Cluster of Unreliable Commodity Hardware. At the core of this cluster is the concept of replication, which in the most basic of terms means that  data is shared between multiple sources.  Replication is used to share information between nodes of the cluster, which provides for cluster reliability and fault tolerance.

Replication between Nodes
Replication between Nodes (source)

If you’d like to learn more about replication in Cloudant and CouchDB, you can read more using the links below:

Cloudant is a clustered NoSQL database services that provides an extremely powerful and searchable data store.  It is designed to power the web and mobile apps, and all information is exposed via REST services. Since the IBM Cloudant service is based on CouchDB (and not so coincidentally, IBM is a major contributor to the CouchDB project), replication is also core the the Cloudant service.

With replication, you only have to write your data/changes to a single node in the cluster, and replication takes care of propagating these changes across the cluster.

If you are building apps for the web or mobile, there are options to extend the data replication locally either on the device or in the browser.   This means that you can have a local data store that automatically pushes and/or pulls data from the remote store using replication, and it can be done either via native languages, or using JavaScript.

If you want to have local replication in either a web or hybrid (Cordova/PhoneGap) app, you can use PouchDB.  PouchDB is a local JavaScript database modeled after CouchDB and implements that CouchDB replication API.  So, you can store your data in the browser’s local storage, and those changes will automatically be replicated to the remote Cloudant store.  This works in the browser, in a hybrid (web view) app, or even inside of a Node.js instance. Granted, if you’re in-browser you’ll need to leverage the HTML5 cache to have your app cached locally.

If you are building a native app, don’t worry, you can take advantage of the Cloudant Sync API to leverage the local data store with replication.  This is available for iOS and Android, and implements the CouchDB replication API.

The sample app that I showed in the presentation is a native iOS application based on the GeoPix MobileFirst sample app that I detailed in a previous post.  The difference is that in this case I showed it using the Cloudant Sync API, instead of the MobileFirst data wrapper classes, even though it was pointing at the exact same Cloudant database instance.  You can see a video of the app in action below.

All that you have to do is create a local data store instance, and then use replication to synchronize data between the local store and a remote store.

Replication be either one-way (push or pull), or two-way.  So, any changes between the local and remote stores are replicated across the cluster.  Essentially, the local data store just becomes a node in the cluster.  This provides complete access to the local data, even if there is no network available.  Just save your data to the local store, and replication takes care of the rest.

In the native Objective-C code, you just need to setup the CDTDatastore manager, and initialize your datastore instance.

self.manager = [[CDTDatastoreManager alloc] initWithDirectory:path error:nil];
self.datastore = [self.manager datastoreNamed:@"geopix" error:nil];

Once your datastore is created, you can read/write/modify any data in the local store.  In this case I am creating a generic data object (basically  like a JSON object), and creating a document containing this data.  A document is a record within the data store.

You can add attachments to the document or modify the document as your app needs.  In the code below, I add a JPG atttachment to the document.

//create a document revision
CDTMutableDocumentRevision *rev = [CDTMutableDocumentRevision revision];
rev.body = @{
			 @"sort": [NSNumber numberWithDouble:[now timeIntervalSince1970]],
			 @"clientDate": dateString,
			 @"latitude": [NSNumber numberWithFloat:location.coordinate.latitude],
			 @"longitude": [NSNumber numberWithFloat:location.coordinate.longitude],
			 @"altitude": [NSNumber numberWithFloat:location.altitude],
			 @"course": [NSNumber numberWithFloat:location.course],
			 @"type": @"com.geopix.entry"
			 };

//add the jpg attachment
NSData *imageData = UIImageJPEGRepresentation(image, 0.1);
[imageData writeToFile:imagePath atomically:YES];
 
CDTUnsavedFileAttachment *att1 = [[CDTUnsavedFileAttachment alloc]
								  initWithPath:imagePath
								  name:imageName
								  type:@"image/jpeg"];

rev.attachments = @{ imageName: att1 };

//create a new document from the revision
NSError *error = nil;
CDTDocumentRevision *doc = [self.datastore createDocumentFromRevision:rev error:&error];

if (doc == nil) {
	[logger logErrorWithMessages:@"Error creating document: %@", error.localizedDescription];
}

[logger logDebugWithMessages:@"Document created ID: %@", doc.docId];

Replication is a fire-and-forget process.  You simply need to initialize the replication process, and any changes to the local data store will be replicated to the remote store automatically when the device is online.

//initialize the replicator factory with the local data store manager
CDTReplicatorFactory *replicatorFactory = 
	[[CDTReplicatorFactory alloc] initWithDatastoreManager:self.manager];

NSURL *remoteDatabaseURL = [NSURL URLWithString:REMOTE_DATABASE_URL];

//setup push replication for local->remote changes
NSError *error = nil;
CDTPushReplication *pushReplication = 
	[CDTPushReplication replicationWithSource:self.datastore target:remoteDatabaseURL];

//create the replicator instance
self.replicator = [replicatorFactory oneWay:pushReplication error:&error];
if (!self.replicator) {
	[logger logErrorWithMessages:@"An error occurred: %@", error.localizedDescription];
}

//assign the replicator delegate
self.replicator.delegate = self;

//auto start replication
error = nil;
if (![self.replicator startWithError:&error]) {
	[logger logErrorWithMessages:@"An error occurred: %@", error.localizedDescription];
}

By assigning a replicator delegate class (as shown above), your app can monitor and respond to changes in replication state.  For example, you can update status if replication is in progress, complete, or if an error condition was encountered.

- (void)replicatorDidChangeState:(CDTReplicator *)replicator {
    [logger logDebugWithMessages:@"Replicator changed State: %@", [CDTReplicator stringForReplicatorState:replicator.state]];
}

- (void)replicatorDidChangeProgress:(CDTReplicator *)replicator {
    [logger logDebugWithMessages:@"Replicator progress: %d/%d", replicator.changesProcessed, replicator.changesTotal];
    
    NSDictionary *userInfo = @{ @"status":[NSString stringWithFormat:@"%d/%d", replicator.changesProcessed, replicator.changesTotal] };
    
    [[NSNotificationCenter defaultCenter]
     postNotificationName:@"ReplicationStatus"
     object:self
     userInfo:userInfo];
}

- (void)replicatorDidError:(CDTReplicator *)replicator info:(NSError *)info {
    [logger logErrorWithMessages:@"An error occurred: %@", info.localizedDescription];
    self.replicator = nil;
    
    [[NSNotificationCenter defaultCenter]
     postNotificationName:@"ReplicationError"
     object:self];
}

- (void)replicatorDidComplete:(CDTReplicator *)replicator {
    [logger logDebugWithMessages:@"Replication completed"];
    self.replicator = nil;
    
    [[NSNotificationCenter defaultCenter]
     postNotificationName:@"ReplicationComplete"
     object:self];
}

If you want to access data from the local store, it is always available within the app, regardless of whether or not the device has an active internet connection.  For example, this method will return all documents within the local data store.

-(NSArray*) getLocalData {
    
    NSArray *docs = [self.datastore getAllDocuments];
    return docs;
}

Be sure to review the documentation and/or Cloudant Synch API source code for complete details.

Helpful Links

Updated: Parallax Effects in Hybrid/Web Apps

A while back I wrote about adding parallax effects to your HTML/JS experiences to make them feel a bit richer and closer to a native experience.  I’ve just added this subtle (key word *subtle*) effect to a new project and made a few changes I wanted to share here.

If you are wondering what I am talking about with “parallax effects” – Parallax movement is where objects in the background move at a different rate than objects in the foreground, thus causing the perception of depth.  Read more about it if you’re interested.

First, here’s a quick video of this latest app in action.  It’s a hybrid MobileFirst app, but this technique could be used in any Cordova/PhoneGap/MobileFirst/mobile web app experience.  The key is to keep it subtle and not too much “in your face”, and yes, it is very subtle in this video.  You have to watch closely.

The techniques that I wrote about in the previous post still apply – I’ve just added a bit more to cover more use cases.

First let’s look at the CSS.

body {
    background-image: url('../images/cloud_advisor_bkgd.png');
    background-attachment: fixed;
    background-position: center;
    background-size: auto 120%;
}

This sets the background image and default position.  The distinct change here is that I set the background size to “auto” width and 120% height.  In this case, you can have a huge image that shrinks down to just slightly larger than the window size, or a small image that scales up to a larger window size.  This way you don’t end up with seams in a repeated background or a background that is too big to highlight the parallax effect effectively.

Next let’s take a quick look at the JS involved.

var position = "center";
var lastPosition = "center";
var contentCSS = "";
var body = $("body");
var content = $(".content");
window.suspendAnimation = false;

var xMovement = 15;
var yMovement = 30;
var halfX = xMovement/2;
var halfY = yMovement/2;

window.ondeviceorientation = function(event) {
 var gamma = event.gamma/90;
 var beta = event.beta/180;

 var temp = 0;

 //fix for holding the device upside down
 if ( gamma >= 1 ) {
  gamma = 2- gamma;
 } else if ( gamma <= -1) {
  gamma = -2 - gamma;
 }

 // shift values/motion based upon device orientation
 switch (window.orientation) {
  case 90:
   temp = gamma;
   gamma = beta;
   beta = temp;
   break;
  case -90:
   temp = -gamma;
   gamma = beta;
   beta = temp;
   break;

 }

 // update positions to be used for CSS
 var yPosition = -yMovement - (beta * yMovement);
 var xPosition = -xMovement - (gamma * xMovement);
 var contentX = (-xMovement - xPosition)/2;
 var contentY = (-yMovement - yPosition)/2;

 // generate css styles
 position = xPosition.toFixed(1) + "px " + yPosition.toFixed(1) + "px";
 contentCSS = "translate3d( " + (contentX.toFixed(1)) + "px, " + (contentY.toFixed(1)) + "px, " + " 0px)";
}

function updateBackground() {

 if (!window.suspendAnimation) {
  if ( position.valueOf() != lastPosition.valueOf() ) {

   body.css( "background-position", position);
   content.css( "-webkit-transform", contentCSS);
   lastPosition = position;
  }
 } else {
  lastPosition = "translate3d(0px, 0px, 0px)";;
 }

 window.requestAnimationFrame(updateBackground);
}

window.requestAnimationFrame(updateBackground);

The html where this would be used would be something like this:

<body>
  <div class="content">put your foreground stuff here.</div>
</body>

There are some subtle but important changes here:

  1. In the requestAnimationFrame loop, it only applies changes *if* there are changes to apply.  This prevents needless calls to apply CSS even if the CSS styles hadn’t changed.  In this, I also truncate the numeric CSS string so that it isn’t reapplying CSS if the position should shift by 0.01 pixels. Side note: If you aren’t using requestAnimationFrame for HTML animations, you should learn about it.
  2. If you used my old code and were holding the device upside down, it wouldn’t work.  Not even a little bit.  This has that fixed (see comments inline above).
  3. This moves the background in CSS, which doesn’t cause browser reflow operations, and moves the foreground content (inside of a div) using translate3d, which also doesn’t cause browser reflow operations.  This helps keep animations smooth and the UX performing optimally.
  4. I also added a global variable to turn parallax on and off very quickly, if you need it.

The result is a faster experience that is more efficient and less of a strain on CPU and battery.  Feel free to test this technique out on your own.

If you use the code above, you can modify the xMovement and yMovement variables to exaggerate the parallax effect.

Unified Multi-Platform Push Notifications with IBM MobileFirst

Push notifications, love them or hate them, are everywhere and there’s no getting around it. Push notifications are short messages that can be sent to mobile devices regardless of whether the apps are actually running. They can be used to send reminders, drive engagement with the mobile app, notify completion of long running processes, and more. Push notifications send information to you in real time, rather than you having to request that information.

Regardless of the platform or native/hybrid development approach, push notifications have to leverage the messaging infrastructure of the platform. iOS apps that have push notifications must use APNS (Apple Push Notification Service), Android apps must use GCM (Google Cloud Messaging), Windows Phone apps use MPNS (Microsoft Push Nofitication Service), and others use SMS gateways.

If you are building a back-end infrastructure to manage your application’s data, and you want to leverage push notifications, then guess what? You also have to build the hooks to manage subscription and distribution of push notifications for each platform.

If you’re building your app with IBM MobileFirst, guess what? You already have a unified API to communicate with all of these platform push notification services with a single API. Yes, you read that correctly – in addition to operational analytics, remote logging, simple data adaptersmobile application sharing, app management, encrypted offline storage, SSO, and support for both native and hybrid paradigms, IBM MobileFirst also has a single, unified multi-platform push notification API that simplifies your development effort for subscribing and managing push notifications on numerous platforms. Check out the video below for additional detail.

The unified push notification API allows you to develop your app against a single API, yet deliver push notifications to multiple platforms, and it works with both hybrid (HTML/CSS/JS) apps, as well as native apps.

MobileFirst Push Notification Mechanism
MobileFirst Push Notification Mechanism

 

The IBM MobileFirst push architecture supports numerous scenarios, including user targeted or broadcast messages.

You will still have to build the logic to subscribe devices for messaging, and dispatch push notification messages, but you’ll only have to do it once against the unified API – not once for each platform.

The apps that I showed in the video above are sample apps taken straight from the IBM MobileFirst platform developer guide for iOS and Android, and can be accessed in their entirety (with both client and server code) using the links below:

The client-side code will vary slightly depending on the native platform or hybrid approach, but the server-side implementation will be exactly the same.

When configuring your server for sending push notifications, be sure to follow the platform-specific steps to provision the apps/server for sending and receiving push notifications.

Within an adapter service on the MobileFirst server, you need to define an event source for push notifications.

WL.Server.createEventSource({
 name: 'PushEventSource',
 onDeviceSubscribe: 'deviceSubscribeFunc',
 onDeviceUnsubscribe: 'deviceUnsubscribeFunc',
 securityTest:'PushApplication-strong-mobile-securityTest'
});

On the client app, you’ll need to subscribe for messages from the event source. See the hybrid or native code linked to above for syntax and examples.

Once your clients are subscribed, you can use a single server-side implementation to distribute messages to client apps. Below is an excerpt from the sample application which demonstrates sending a push notification to all devices for a particular user (on any platform):

function submitNotification(userId, notificationText){
	var userSubscription =
		WL.Server.getUserNotificationSubscription('PushAdapter.PushEventSource', userId);

	if (userSubscription==null){
		return { result: "No subscription found for user :: " + userId };
	}

	var badgeDigit = 1;

	var notification =
		WL.Server.createDefaultNotification(notificationText, badgeDigit, {custom:"data"});

	WL.Logger.debug("submitNotification >> userId :: " + userId + ", text :: " + notificationText);

	WL.Server.notifyAllDevices(userSubscription, notification);

	return {
		result: "Notification sent to user :: " + userId
	};
}

From the MobileFirst console, you will be able to monitor and manage event sources, platforms, and the devices that are consuming push notifications.

Push Notifications on the MobileFirst Console
Push Notifications on the MobileFirst Console

 

If you were wondering, yes, these can be cloud-hosted on IBM BlueMix and yes, it can also be installed on-premise on your own server in your data center.  You have the option to configure your physical or cloud servers however you want.

Not sure where to go next? Maybe these will help:

UX & Mobile Apps Leveraging the IBM MobileFirst Platform

When you are developing a mobile app (or website, or mobile web, or TV app, etc..) you should always ask yourself “What kind of an impact does this have on the end user?” It doesn’t matter whether you are creating enterprise apps or games, or anything in between. Every development decision that you make should be weighed upon it’s impact to the overall impact it has on the end user. Simply put: if your app sucks, nobody is going to want to use it.

When building mobile apps using IBM MobileFirst you have two options for a user interface layer; you can write a native app, or you can write a hybrid app using HTML, CSS, & JavaScript.

Native VS HTML Hybrid

So, what kind of an impact does the addition of IBM MobileFirst have on the app?

NONE, granted the app’s UX can vary depending upon whether you are developing a native app or a hybrid app.

IBM MobileFirst Platform Foundation is a platform that consists of a server tier and client-side SDK. If you are developing a native app, the SDK/API provides access to MobileFirst platform features, like user authentication, app version management, data access through adapters, encrypted storage, unified push notification, remote log collection, and more. If you are developing a hybrid app, the app’s UX must be developed complete inside of the web view container. The MobileFirst Foundation SDK provides additional functionality just like mentioned above for the native SDK, plus a few classes that enable native dialogs and a few native UI elements, but for the most part, there is very, very minimal impact on the user’s experience.

When building any kind of mobile app, regardless of whether it is native or hybrid, you need to pay attention to what the user experiences. Are you following human interaction or design guidelines for the platform? Are you forcing your user to go through unnecessary or redundant steps? Are you making forms more complex than they need to be? Are you forcing multiple taps for a simple interaction? Can things be simplified?

The IBM MobileFirst Platform does not add any additional overhead for UX processes.

The IBM MobileFirst platform can be used to develop native apps on iOS, Android, Windows Phone, or Java ME platforms. Follow native coding conventions and UX guidelines for each individual platform. Make sure you follow these guidelines, otherwise your app may feel alien within the ecosystem, or may be rejected from app store approval altogether.

What should you think about when building a hybrid app leveraging IBM MobileFirst?

First, it depends on your hybrid approach. If you are using the for Xamarin hybrid approach for MobileFirst apps, then your considerations will be much like writing a native app.

If you are using the HTML/CSS/JavaScript approach (leveraging the Apache Cordova container), then you really want to focus on the user’s experience inside of the HTML container. You want to make sure the UI feels like “an app”, not like “a web page”. There are many client-side frameworks that help address this need. Feel free to use any of them, or roll your own – just keep the UX/human interaction guidelines in mind.

(this is by no means an exhaustive list, there are more out there)

Make sure you’re building for touch interactivity, addressing animations correctly to minimize browser reflow operations, and more… Read this post on Dzone that I wrote last year for a lot more detail on performance considerations for hybrid or mobile web apps.

If you are using any of these (or none of these), also don’t forget an architectural pattern/framework for helping keep your code organized and consistent. Read this post on hybrid/web app architectural patterns and considerations for even more detail.

For both native and hybrid approaches, you also want to consider impacts of perceived performance vs actual raw processing  power. These techniques deliver the appearance that the app is fast and responsive, instead of sluggish or locked while waiting to perform an action. Perceived performance improvements can be achieved simply by providing instant feedback, performing animations during an asynchronous request, or preemptive tasking. Don’t miss this post, where I go into perceived performance in mobile apps in great detail.