Category Archives: enterprise

Adaptive mobile apps that change based on personal context

That title get your attention?  Yes, it really read “Adaptive mobile apps that change based on personal context” – with near real-time rules application, without much extra development effort.  If that sounds interesting to you, or like a product you might want to use within your own apps, then you might want to check out this site where you can get involved in the product’s development: http://adaptiveexperience.mybluemix.net/

IBM is looking for your input on creating these types of mobile app experiences. User experiences within a single app that can be dramatically different per user based on location, past behavior, profile information, social media activity, and so much more.  With this behavior being driven by configurable rules that can be changed without redeploying an app to the app store.

How it works for your customer

Consider this scenario:

Jon and Andrea download the mobile app for S&W, a retailer known for its attention to providing great customer service. Over the next month, Jon and Andrea use the app to browse and discover content and merchandise differently.

Jon primarily navigates to sports related content for his favorite teams to find gear and clothes for travel to his favorite team’s games. Andrea scours the app for sales and fashion trends and usually ends up following her favorite designers.

Andrea and Jon go to a baseball game together. She’s never enjoyed watching it, so she opens up the S&W app to entertain herself, and her app’s navigation quickly steers her through Spring fashion articles.

Jon however, wants to replace the hat he’s worn the last three times the team lost, and since he’s in the stadium, his S&W app opens right up to the team’s gear page. The app knows he’s out of town and tells him how to get to an S&W store.

How it works for the dev team

Consider another scenario:

One of the developers on the team, George, sets up the system and application. He then gives access to Janet who is responsible for the customer experience.

Janet writes rules defining how the application could adapt and become more personalized based on inputs like , social media, geolocation, app usage, or customer information data.

Once Janet has built out her rules, she simply hits ‘Submit’ and can immediately see her clever interactions reflected in the mobile application without having to involve the development team.

Analytics let Janet know which adaptations are working best, and helps her find new opportunities to optimize the app’s user experience.

Sound interesting yet?  Check it out, and get involved in the product development at:  http://adaptiveexperience.mybluemix.net/

We’re not talking about a content management system, or translation based on locale, instead a rules-driven product that can adapt literally every aspect of your app:  customize the user interface, enable or disable different features, customized messaging and notifications, and much more, all variable based upon the user context.  This can be used to present contextually relevant information, drive adoption, provide more/less data depending on your physical context, and so much more.

It won’t be tied to a specific UI framework, won’t be tied to a specific content management system, isn’t attempting to re-create Google Now or Apple Proactive Assistance.  Rather, a set of tools and a rules engine that enable you to customize and tailor the app experience to the individual user.

Head over to http://adaptiveexperience.mybluemix.net/ to learn more and get involved!

GeoPix: A sample iOS app powered by IBM MobileFirst for Bluemix

In this post I’d like to show a fairly simple application that I put together which shows off some of the rich capabilities for IBM MobileFirst for Bluemix that you get out of the box – All with an absolute minimal amount of your own developer effort.  Bluemix, of course, being IBM’s platform as a service offering.

GeoPix is a sample application leveraging IBM MobileFirst for Bluemix to capture data and images on a mobile device, persist that data locally (offline), and replicate that data to the cloud. Since it’s built with IBM MobileFirst, we get lots of things out of the box, including operational analytics, user authentication, and much more.

(full source code at the bottom of this post)

Here’s what the application currently does:

  • User can take a picture or select an image from the device
  • App captures geographic location when the image is captured
  • App saves both the image and metadata to a local data store on the device.
  • App uses asynchronous replication to automatically save any data in local store up to the remote store whenever the network is available
  • Oh yeah, can’t forget, the user auth is via Facebook
  • MobileFirst provides all the analytics we need.  Bluemix provides the cloud based server and Cloudant NoSQL data store.
  • All captured data is available on a web based front-end powered by Node.js

Here’s a video of it in action:

… and you can check out the web interface at geopix.mybluemix.net.

(full source code at the bottom of this post)

This is powered by the iOS 8 MobileFirst application boilerplate on Bluemix.  With this application template you can have your backend infrastructure setup within minutes, and it includes:

  • User authentication
  • Usage/operational analytics
  • Cloudant NoSQL DB
  • Simplified Push Notifications
  • Node.js backend

In this sample I’m using everything but the Push Notifications service.  I’m using user authentication, the Cloudant DB (offline/local store and remote/cloud store), and the node.js backend.  You get the operational analytics automatically.

To get started, you just need to create a new iOS 8 mobile application on Bluemix.  See my video series on Getting Started with IBM MobileFirst for Bluemix for a complete walkthrough of creating a new app using MobileFirst for Bluemix, or check out the Getting Started Guide in the official docs.

You need to initialize your app, and make sure you have setup the Facebook identity provider.  You can create your Facebook authentication at https://developers.facebook.com/.  Once the user is authenticated, the client app is fully functional.

The app UI is very simple, basically just two buttons for capturing images (the last captured image shows up in the background):

App's main UI
App’s main UI

There’s also a gallery for viewing local images:

Local gallery view
Local gallery view

Capturing Location

Capturing data is very straightforward.  The geographic location is captured using Apple’s Core Location framework.  We just need to implement the CLLocationManagerDelegate protocol:

- (void)locationManager:(CLLocationManager *)manager
 didUpdateLocations:(NSArray *)locations {

    self.currentLocation = [locations lastObject];
    NSDate* eventDate = self.currentLocation.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (abs(howRecent) < 15.0) {
    // If the event is recent, do something with it.
    locationLabel.text = [NSString stringWithFormat:@" Lat: %+.5f, Lon: %+.5f\n",
      self.currentLocation.coordinate.latitude,
      self.currentLocation.coordinate.longitude];
    }
}

Then initialize CLLocationManager using our class as the location manager’s delegate:

if (self.locationManager == nil)
  self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.pausesLocationUpdatesAutomatically = YES;

Capturing Images

Capturing images from the device is also very straightforward.  In the app I leverage Apple’s UIImagePickerController to allow the user to either upload an existing image or capture a new image.  See the presentImagePicker and didFinishPickingMediaWithInfo below. All of this standard practice using Apple’s developer SDK:

- (void) presentImagePicker:(UIImagePickerControllerSourceType) sourceType {
 if ( sourceType == UIImagePickerControllerSourceTypeCamera  && ![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
  [logger logErrorWithMessages:@"device has no camera"];
  UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@"Error"
                 message:@"Device has no camera"
                delegate:nil
             cancelButtonTitle:@"OK"
             otherButtonTitles: nil];
  [myAlertView show];
 };

 if ( sourceType != UIImagePickerControllerSourceTypeCamera || [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ){
  UIImagePickerController *picker = [[UIImagePickerController alloc] init];
  picker.delegate = self;
  picker.allowsEditing = NO;
  picker.sourceType = sourceType;

  [self presentViewController:picker animated:YES completion:NULL];
 }
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

 [logger logDebugWithMessages:@"didFinishPickingMediaWithInfo"];
 UIImage *image = info[UIImagePickerControllerOriginalImage];
 currentImage.image = image;
 [[DataManager sharedInstance] saveImage:image withLocation:self.currentLocation];
 [picker dismissViewControllerAnimated:YES completion:nil];
}

Persisting Data

If you notice in the didFinishPickingMediaWithInfo method above, there is a call to the DataManager’s saveImage withLocation method. This is where we save data locally and rely on Cloudant’s replication to automatically save data from the local data store up to the Cloudant NoSQL database.  This is powered by the iOS 8 Data service from Bluemix.

The first thing that we will need to do is initialize the local and remote data stores. Below you can see my init method from my DataManager class. In this, you can see the local data store is initialized, then the remote data store is initialized. If either data store already exists, the existing store will be used, otherwise it is created.

-(id) init {
 self = [super init];

 if ( self ) {
  logger = [IMFLogger loggerForName:NSStringFromClass([self class])];
  [logger logDebugWithMessages:@"initializing local datastore 'geopix'..."];

  // initialize an instance of the IMFDataManager
  self.manager = [IMFDataManager sharedInstance];

  NSError *error = nil;
  //create a local data store
  self.datastore = [self.manager localStore:@"geopix" error:&error];

  if (error) {
   [logger logErrorWithMessages:@"Error creating local data store %@",error.description];
  }

  //create a remote data store
  [self.manager remoteStore:@"geopix" completionHandler:^(CDTStore *store, NSError *error) {
   if (error) {
    [logger logErrorWithMessages:@"Error creating remote data store %@",error.description];
   } else {
    [self.manager setCurrentUserPermissions:DB_ACCESS_GROUP_MEMBERS forStoreName:@"geopix" completionHander:^(BOOL success, NSError *error) {
     if (error) {
      [logger logErrorWithMessages:@"Error setting permissions for user with error %@",error.description];
     }

     [self replicate];
    }];
   }
  }];

  //start replication
  [self replicate];
 }

 return self;
} 

Once the data stores are created, you can see that the replicate method is invoked.  This starts up the replication process to automatically push changesfrom the local data store to the remote data store “in the cloud”.

Therefore, if you’re collecting data when the app is offline, then you have nothing to worry about.  All of the data will be stored locally and pushed up to the cloud whenever you’re back online – all with no additional effort on your part.  When using replication with the Cloudant SDK, you just have to start the replication process and let it do it’s thing… fire and forget.

In my replicate function, I setup CDTPushReplication for pushing changes to the remote data store.  You could also setup two-way replication to automatically pull new changes from the remote store.

-(void) replicate {
 if ( self.replicator == nil ) {
  [logger logDebugWithMessages:@"attempting replication to remote datastore..."];

  __block NSError *replicationError;
  CDTPushReplication *push = [self.manager pushReplicationForStore: @"geopix"];
  self.replicator = [self.manager.replicatorFactory oneWay:push error:&replicationError];
  if(replicationError){
   // Handle error
   [logger logErrorWithMessages:@"An error occurred: %@", replicationError.localizedDescription];
  }

  self.replicator.delegate = self;

  replicationError = nil;
  [logger logDebugWithMessages:@"starting replication"];
  [self.replicator startWithError:&replicationError];
  if(replicationError){
   [logger logErrorWithMessages:@"An error occurred: %@", replicationError.localizedDescription];
  }else{
   [logger logDebugWithMessages:@"replication start successful"];
  }
 }
 else {
  [logger logDebugWithMessages:@"replicator already running"];
 }
}

Once we’ve setup the remote and local data stores and setup replication, we now are ready to save the data the we’re capturing within our app.

Next is my saveImage withLocation method.  Here you can see that it creates a new CDTMutableDocumentRevision object (this is a generic object for the Cloudant NoSQL database), and populates it with the location data and timestamp.   It then creates a jpg image from the UIImage (passed in from the UIImagePicker above) and adds the jpg as an attachment to the document revision.  Once the document is created, it is saved to the local data store.   We then let replication take care of persisting this data to the back end.

-(void) saveImage:(UIImage*)image withLocation:(CLLocation*)location {

 [logger logDebugWithMessages:@"saveImage withLocation"];

 //save in background thread
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {

  [logger logDebugWithMessages:@"creating document..."];

  NSDate *now = [NSDate date];
  NSString *dateString = [NSDateFormatter localizedStringFromDate:now
                 dateStyle:NSDateFormatterShortStyle
                 timeStyle:NSDateFormatterFullStyle];

  // Create a document
  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"
      };

  [logger logDebugWithMessages:@"creating image attachment..."];

  NSDate *date = [NSDate date];
  NSString *imageName = [NSString stringWithFormat:@"image%f.jpg", [date timeIntervalSince1970]];

  NSString *tempDirectory = NSTemporaryDirectory();
  NSString *imagePath = [tempDirectory stringByAppendingPathComponent:imageName];

  [logger logDebugWithMessages:@"saving image to temporary location: %@", imagePath];

  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 };

  [self.datastore save:rev completionHandler:^(id savedObject, NSError *error) {
   if(error) {
    [logger logErrorWithMessages:@"Error creating document: %@", error.localizedDescription];
   }
   [logger logDebugWithMessages:@"Document created: %@", savedObject];
  }];

  [self replicate];
 });
}

If we want to query data from either the remote or local data stores, we can just use the performQuery method on the data store. Below you can see a method for retrieving data for all of the images in the local data store.

-(void) getLocalData:(void (^)(NSArray *results, NSError *error)) completionHandler {

 NSPredicate *queryPredicate = [NSPredicate predicateWithFormat:@"(type = 'com.geopix.entry')"];
 CDTCloudantQuery *query = [[CDTCloudantQuery alloc] initWithPredicate:queryPredicate];

 [self.datastore performQuery:query completionHandler:^(NSArray *results, NSError *error) {

  completionHandler( results, error );
 }];
}

At this point we’ve now captured an image, captured the geographic location, saved that data in our local offline store, and then use replication to save that data up to the cloud whenever it is available.

AND…

We did all of this without writing a single line of server-side logic.   Since this is built on top of MobileFirst for Bluemix, all the backend infrastructure is setup for us, and we get operational analytics to monitor everything that is happening.

With the operational analytics we get:

  • App usage
  • Active Devices
  • Network Usage
  • Authentications
  • Data Storage
  • Device Logs (yes, complete debug/crash logs from devices out in the field)
  • Push Notification Usage

Sharing on the web

Up until this point we haven’t had to write any back-end code. However the mobile app boilerplate on Bluemix comes with a Node.js server.  We might as well take advantage of it.

I exposed the exact same data captured within the app on the Node.js service, which you can see at http://geopix.mybluemix.net/.

Web UI
Web UI

The Node.js back end comes preconfigured to leverage the express.js framework for building web applications.  I added the jade template engine and Leaflet for web-mapping, and was able to crank this out ridiculously quickly.

The first thing we need to do is make sure  we have our configuration variables for accessing the Cloudant service from our node app.  These are environment vars that you get automatcilly if you’re running on Bluemix, but you need to set these for your local dev environment:

var credentials = {};

if (process.env.hasOwnProperty("VCAP_SERVICES")) {
 // Running on Bluemix. Parse out the port and host that we've been assigned.
 var env = JSON.parse(process.env.VCAP_SERVICES);
 var host = process.env.VCAP_APP_HOST;
 var port = process.env.VCAP_APP_PORT;

 credentials = env['cloudantNoSQLDB'][0].credentials;
}
else {

 //for local node.js server instance
 credentials.username = "cloudant username here";
 credentials.password = "cloudant password here";
 credentials.url = "cloudant url here";
}

Next we’ll add our URL/content mappings:

app.get('/', function(req, res){
  prepareData(res, 'map');
});

app.get('/list', function(req, res){
  prepareData(res, 'list');
});

Next you’ll se the logic for querying the Cloudant data store and preparing the data for our UI templates. You can customize this however you want – caching for performance, refactoring for abstraction, or whatever you want. All interactions with Cloudant are powered by the Cloudant Node.js Client

var prepareData = function(res, template) {
 var results = [];

 //create the index if it doesn't already exist
 var sort_index = {name:'sort', type:'json', index:{fields:['sort']}};
 geopix.index(sort_index, function(er, response) {
  if (er) {
   throw er;
  }

  //perform the search
  //we're just pulling back all
  //data captured ("sort" will be numeric)
  var selector = {sort:{"$gt":0}};
  geopix.find({selector:selector, sort:["sort"]}, function(er, result) {
   if (er) {
    throw er;
   }

   //prepare data for template
   for (var x=0; x<result.docs.length; x++) {
    var obj = result.docs[x];

    for (var key in obj._attachments) {
     obj.image = credentials.url + "/" + database + "/" + obj._id +"/" + key;
     break;
    }

    results.push( obj );
   }
   res.render(template, { results:results});
  });
 });
};

After the prepareData method has prepared data for formatting in the UI, the template is rendered by invoking Jade’s render method:

res.render(template, { results:results});

This will render whichever template was passed in – I have two: map.jade (the map template) and list.jade (the list template). You can check out the list template below, and see it in action here: http://geopix.mybluemix.net/list

html
  head
 title GeoPix - powered by Bluemix
 link(href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css' rel='stylesheet')
 link(href='/public/css/index.css' rel='stylesheet')
 meta(name="viewport" content="width=device-width, initial-scale=1")
  body
 div(class='well')
  h1 GeoPix - Powered by Bluemix
  p
   a(href='/') Map
   &nbsp;|&nbsp;
   a(href='/list') List
 div(class="container-fluid")
  each val, index in results
   div(class="col-md-6")
    div(class="panel panel-default")
     div(class="panel-heading")
      h3= val.clientDate
     div(class="panel-body")
      img(src=val.image)
      p= 'latitude: ' + val.latitude + ", longitude:" + val.longitude + ", altitude:" + val.altitude

In the map view I used the Leaflet map engine and Open Street Map data, along with the Leaflet Marker Cluster plugin for displaying clustered results.

Source Code

You can check out the web interface live at: http://geopix.mybluemix.net/.  If you want to setup the environment on your own, you can grab the complete source code at:

Helpful Links

Ready to start building your own apps on IBM Bluemix?  Just head over to http://bluemix.net and get a free developer trial today!

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:

IBM MobileFirst – Powering the IBM & Apple Partnership

Back in July, Apple and IBM announced a global strategic partnership to redefine how enterprises use mobile applications. Well, last week IBM and Apple announced the first set of apps developed from this partnership.

ibm-apple

The first set of applications include industry-specific applications designed to “redefine how work gets done”. The first set includes apps for air travel, banking and finance, insurance, government, retail, and telecom industries, and are just the beginning of the IBM/Apple parnership. Check out the press release for full details on the apps.

Apple’s VP of Worldwide Marketing, Phil Schiller is quoted saying: “The business world has gone mobile, and Apple and IBM are bringing together the world’s best technology with the smartest data and analytics to help businesses redefine how work gets done.”

So what is powering this transformation?  

The IBM MobileFirst Platform. That’s what.

MobileFirst-Logo

From the press release:


To supplement the IBM MobileFirst for iOS apps, the partnership between Apple and IBM offers business customers additional levels of capability integrated for enterprise mobility, including:

  • Mobile Platform and Enterprise Integration – Leveraging IBM’s global industry consulting expertise, client experience design and enterprise systems integration from analytics, workflow and cloud storage, to fleet-scale device management, security and integration. Enhanced mobile management includes a private app catalog, data and transaction security services, and productivity suite for all IBM MobileFirst for iOS solutions. In addition to on-premise software solutions, all these services will be available on Bluemix—IBM’s development platform on the IBM Cloud Marketplace.
  • Supply, activate and manage – Streamlined end-to-end procurement, deployment and lifecycle management — at scale; along with cloud solutions for enterprise security, device management, and data and process integration. IBM Global Financing leasing options and services to allow organizations to keep pace with latest device releases.
  • AppleCare for the Enterprise  – Providing IT departments and end users with 24/7 assistance for their devices from Apple’s award-winning customer support group, with on-site service delivered by IBM.

So, what does this mean from a more detailed/technical perspective?

MobileFirst Platform Foundation

Let’s look at the MobileFirst Platform Foundation, which consists of MobileFirst Platform Server (console and app management), client-side SDKs for native or hybrid apps, the MobileFirst Studio & CLI tools, and the MobileFirst Application Center.

mobilefirst-architecture
MobileFirst High-level System Architecture

The MobileFirst Platform Server and Client-side SDKs deliver security features, data integration features, app management features, unified push notifications, and analytics. From the security perspective, the MobileFirst server and SDK provide user authentication and can integrate with virtually any single-sign-on or identity management provider, and can maintain user authentication across multiple applications.

mfp-sso
Multi-app Single Sign On

The MobileFirst SDK also enables encrypted on-device storage, which can be synched with MobileFirst data adapters (used to expose data to the mobile applications).

For application management, the MobileFirst platform enables you to track versions of an app that are live out in production. From the server console, you can send messages to specific versions of an application, or remotely lock down specific versions of an app. This could be used to force compliance using the latest version of an app, or could be used to lock down an app due to some sort of security issue. You can read more about strategies for managing app versions on the MobileFirst platform here.

Application Management Console
Application Management Console

For data integration, the MobileFirst platform enables developers to leverage data adapters, which are lightweight server-side functions to data in a mobile-friendly format. They can automatically generate JSON objects from database information, leverage server-side compression to reduce network latency, perform object translation to compress large structures into smaller, less verbose packages (IE: SOAP to JSON, etc…).

worklight-adapters
MobileFirst Data Adapters

 

Usage of these data adapters is automatically audited, and is governed by the SDK’s authentication and app management. Server-side developers will be happy to know that data adapters are easy to develop using server-side JavaScript. Client-side developers will be happy to know that the MobileFirst SDK has a consisent client-side API to call any backend system.

The MobileFirst Platform server automatically exposes operational analytics for every app and data adapter managed through the platform. This provides insight into devices/platforms/OS versions that are consuming your applications, server-side collection of client-side app logs, and data adapter usage, all enabled “out of the box”.

MobileFirst Platform Analytics
MobileFirst Platform Analytics

MobileFirst Application Center

The MobileFirst Application Center is reposity of mobile applications that enables an “out of the box” app store for your enterprise. If facilitates the sharing of mobile applications, and enables sharing of feedback and rating information. It also uses access control lists to limit who might be able to install specific applications. If your enterprise has numerous mobile apps, and you need a way to manage distribution of your enterprise-signed iOS apps, then this is the solution for you.

mf-application-center
MobileFirst Application Center

MobileFirst Platform Application Scanning

MobileFirst Platform Application Scanning is set of tools that can scan your JavaScript, HTML, Objective-C, or Java code for security vulnerabilities and coding best practices. Think of it as a security layer in your software development lifecycle.

MobileFirst Quality Assurance

MobileFirst Quality Assurance is a set of tools and features to help provide quality assurance to your mobile applications. It includes automated crash analytics, user feedback and sentiment analysis, in-app bug reporting, over-the-air build distribution to testers, test/bug prioritization, and more.

MobileFirst Protect

MobileFirst Protect is a comprehensive suite of tools that enables an enterprise to manage, virtualize and optimize devices, networks, and apps. This includes Mobile Application Management (MAM), Mobile Device Management (MDM), and Mobile Network Performance Management (MNPM). Take a look at the quick video to see how MobileFirst Protect can help you secure the devices connecting to your enterprise.

 MobileFirst Engage

MobileFirst Engage is a platform that enables you to add analytics to your mobile applications. This can help you identify and understand how users are interacting with your enterprise. You can track mobile engagement, process the data, and provide a contextually relevant experience to your users in realtime.

The IBM MobileFirst Platform provides unparalleled tools to build, manage and monitor reliable and secure applications, manage and secure devices, monitor usage and drive engagement, and bring your enterprise to a mobile reality.

IBM Bluemix Cloud Services

Of course, let’s not forget IBM Bluemix, IBM’s suite of cloud services.  Bluemix covers everything from mobile app integration, business process & workflow, security services, cloud storage, analytics, and even the IBM Watson cognitive platform.  This post is long enough already, so I’ll go into more detail on Bluemix at a later date, but definitely go check it out.  There’s everything from basic node.js or Java server hosting, to app boilerplates/templates, and more.

IBM BlueMix Services
IBM BlueMix Services

 

Strategies for Managing App Versions & Updates With IBM MobileFirst Foundation (aka Worklight)

IBM MobileFirst Foundation provides two mechanisms to manage app versions and updates.  Neither requiring you to write any additional code!

The first is app versioning; MobileFirst Foundation tracks each version of an app that you deploy, and gives you the ability govern or restrict access to specific platforms and versions. App versioning applies to all apps, native or hybrid, on any platform that MobileFirst Foundation supports. The second is Direct Update, which allows you to push new HTML/CSS/JavaScript (web) resources to a MobileFirst hybrid app. Direct Update only applies to hybrid apps, but it works for any platform that MobileFirst supports.

App Version Management

When you deploy an app to the MobileFirst Foundation server, the server will automatically track versions based on the version number specified in you application-descriptor.xml file.

Set Application Version
Set Application Version

When you load the MobileFirst Foundation Server Console, you’ll be able to view all of the deployed app platforms and versions.

The screenshot below shows a hybrid app deployed for both Android and iOS platforms. You would also be able to see the exact same version and platform information for native apps that leverage IBM MobileFirst Foundation.

Managing Versions in the MobileFirst Console (click to enlarge)
Managing Versions in the MobileFirst Console (click to enlarge)

You’ll notice in the MobileFirst console that next to each platform/version you can set the status for that version. This makes it possible to set notification messages for users on specific platforms and versions, or even restrict access to specific platforms and versions.

For example, look at the screenshot above… Version 1.0 on Android is active. Version 1.2 on iOS is active. Version 1.1 on iOS is notifying, and Version 1.0 on iOS is disabled.

There are 3 statuses that can be set for each platform and version combination.: Active, Active Notifying, and Access Disabled.

Set Platform/Version Status
Set Platform/Version Status

When you set the status of a platform/version, this status is only for that specific platform/version pair. This enables you to selectively notify users of specific versions, or even block access to specific versions if they are outdated and no longer supported.

“Active” means that the application is active. Services to this version will operate normally, and no messages will be presented to the user.

“Active Notifying” means that the application is active, services will continue to work, but a message will be presented to the user when the app becomes active, or when a service request is made to the MF server.

Setting Active Notification Message
Setting Active Notification Message

This can be used to send any text-based message to the app users. This could be a deprecation notice, service maintenance notice, or any other general notice.

Within the app, the user will see a message when the app becomes active, or when a request is made to the server. This message can be dismissed, and the app functionality is not impacted in any way.

In-App Active Notification Experience
In-App Active Notification Experience

“Access Disabled” means that access to the application is disabled. In this state, a notification message will be presented to the user, and access from the app version will be disabled. The user will also be presented with an “Upgrade” button, which will redirect the user to any URL, which presumably will be for an updated version of the app.

Setting Disabled Status
Setting Disabled Status

In this state, the app will not be granted access to the MobileFirst/Worklight server. So, if your app requests data from a data adapter, all requests to the adapter from this platform/version will be blocked. If your app initialization code is inside of the Worklight client’s connect:onSuccess handler, then this can prevent your app from loading at all.

In-App Disabled Experience
In-App Disabled Experience

Again, When you set the status of a platform/version, this status is only for that specific platform/version pair.

You can learn more about managing applications through the MobileFirst/Worklight Console using the Administering Worklight applications with Worklight Console online documentation.

Direct Update

MobileFirst hybrid applications leverage Apache Cordova plus MF-specific APIs as a foundation to deliver hybrid apps. Apache Cordova enables developers to build natively-installed cross platform apps using web technologies.

Direct Update is a feature for MobileFirst hybrid apps, which enables you to push updated app content (HTML, CSS, & JavaScript) without the user having to deploy a new version of the app through the app store.

Direct Update is considered an additional security feature b/c it enforces users to use the latest version of the application code. However, when an app uses Direct Update, it *only* updates the web resources.  No native changes or version # changes will be applied. However, it should not be abused. In particular this will bypass the Apple’s app store approval process. You should not overhaul the entire UI and break Apple’s Human Interaction Guidelines, otherwise you could be kicked out of the app store.

Direct Update User Experience
Direct Update User Experience

By default, the update’s user experience is a modal overlay that shows download and installation progress. The updater’s UX can be configured to use silent updates that do not block the user’s experience, can be a completely custom user experience, or can be disabled altogether.  Updates can also be paused or resumed using the JavaScript API so that it does not block the user from performing a critical task, however this would require a custom UI – the default UI does not enable pause/resume.

Updates in the current version of Worklight (6.2) are complete updates containing the entire application (www) code, however MobileFirst Foundation 6.3 (coming this month) will have a Differential Direct Update feature that includes only the changed files. More detail will be posted once this is available.

Direct Update can also be disabled if you don’t want your hybrid apps to update automatically.

For more information on Direct Update, be sure to check out these additional resources:

Additional note:  If you’re wondering by I interchange MobileFirst and Worklight in this post, it’s because Worklight is now MobileFirst Platform Foundation