Last week, Eugene Oksman and I presented a webinar on the new Salesforce Mobile SDK. The SDK lets you develop mobile applications for Force.com and Database.com and the webinar included a high-level overview of the current mobile landscape, our mobile strategy going forward, and how to use the Mobile SDK to develop web and hybrid mobile applications. A recording of the webinar is now available. We’ve also posted the slides and compiled an FAQ based on the questions we received during the webinar. The only missing piece is the code that I demoed during the webinar. The code is available on GitHub and I’d like to highlight some of it here. I’ll organize my code walkthrough in the same order that I demoed the application during the webinar and so here goes. I’ve also included links to the points in the webinar recording that correspond to the respective demos.

Developing Web (HTML5) Mobile Applications Using Visualforce

[Recording]

The first half of the webinar was spent on how you can combine Visualforce with other common web technologies like HTML5, JavaScript and CSS to develop web mobile applications – i.e., applications that are rendered completely via a browser on the mobile device (unlike native apps), but are optimized for a mobile/touch environment. To demo this development approach, I extended the Warehouse sample application that is part of the introductory Force.com Workbook. I built a simple Visualforce page that used jQuery Mobile and JavaScript Remoting to present users with a list of records from the Merchandise__c custom object, and then another screen to display details about each record (a classic List–>Detail UI pattern).

Using Visualforce for Mobile Development

Here’s a small code snippet from the MerchandiseMobile Visualforce page.

<apex:page docType="html-5.0" sidebar="false"
           showHeader="false" standardStylesheets="false"
           cache="false" controller="MerchandiseMobileController" >
...
<head>
<script type="text/javascript">
    var merchansideRecs = new Array();
    var $j = jQuery.noConflict();
    ....
    $j(document).ready(function() {
        $j.mobile.showPageLoadingMsg();
        getMerchandise(function(){
             $j.mobile.hidePageLoadingMsg();
        });
        .....
    });

    function getMerchandise(callback) {
        $j('#merchandiseList').empty();
        //Invoke JS Remoting function to retrieve Merchandising Records
        MerchandiseMobileController.getMerchandiseRecs(function(records, e) {
                                                        showMerchandise(records, callback) },
                                                        {escape:true});
    }

    function showMerchandise(records, callback) {
        merchansideRecs.length = 0;

        //Iterate through Merchandising records and add each rec. to the page DOM using JQuery
        .....
    }
</script>
</head>

<body>
    <div data-role="page" data-theme="b" id="listpage">
       ...
    </div>

    <div data-role="page" data-theme="b" id="detailpage">
        ...
    </div>
</body>
</html>

</apex:page>

A couple of things to highlight here. First, use the ‘docType’ attribute on the <apex:page> tag to mark a Visualforce page as HTML5 (vs the HTML 4.01 default). Second, try and keep the page as lightweight and clean as possible (especially important for rendering the page on mobile devices) by turning off the standard Visualforce headers and stylesheets. Next, notice how the page doesn’t use any of the standard Visualforce tag library (e.g., <apex:form>, <apex:pageBlock>). Instead, the page uses a JavaScript mobile framework like jQuery Mobile (that is what the <div> tags come from) and then binds Force.com data using JavaScript and JavaScript Remoting (via the getMerchandise and showMerchandise functions). This pattern is ideal for mobile web app development since you avoid some of the CSS and JavaScript libraries and page structure that come with the standard Visualforce tag library and that are really optimized for a desktop environment. For mobile pages, you want to avoid the <apex:form> tag in particular since it comes with a viewstate that is not always ideal for a resource constrained environment like a mobile browser.

Looking Like a Native Mobile App

[Recording]

Next, I showed some ways that you can make your web application look like a native application so that customers get a more natural user experience. You can do so with a combination of the User Agent HTTP header, JavaScript and some CSS.

    //Apply iOS native skin, if applicable
    if (navigator.userAgent.indexOf('iPhone') != -1) {
         document.write('<link rel="stylesheet" href="{!URLFOR($Resource.jQueryiOSTheme,
                                                      'ios_inspired/styles.css')}"
                                                       type="text/css"/>');
    }

The above JavaScript snippet detects that the Visualforce page is being accessed from an iPhone by introspecting the User Agent header and then applies a special iOS themed CSS ‘skin’ to make the Web app look like a native iOS application. The only hard part here is finding ready-made CSS ‘themes’ for the iOS, Android and Blackberry platforms. jQuery Mobile for example, doesn’t include any default themes for the various mobile platforms (the one I used during the webinar was from GitHub). However, other JavaScript mobile frameworks (specifically, jQTouch and Sencha Touch) do and so keep that in mind when you’re picking our JavaScript mobile framework.

Responding to Mobile Device Orientation Changes

[Recording]

Next up, how to respond to orientation changes in your mobile web application.

        $j(window).bind( 'orientationchange', function(e){
             changeOrientation(e.orientation);
        });

        function changeOrientation(ori) {
             //Apply CSS changes to respond to the orientation change
             ...
        }

As you can see from the above snippet, it is as simple as using jQuery Mobile to bind to the ‘orientationchange’ event and taking appropriate action (e.g., with the CSS display property) when the user changes the device orientation. The advantage of using jQuery Mobile is that it automatically binds to the ‘resize’ event if the mobile browser does not support the standard ‘orientationchange’ event. Note that during the webinar I demoed a simple ‘split-view’ on the Merchandise detail page in Landscape mode (and hid the split-view in Portrait mode). This split-view design and code is for demo purposes only and if you’re interested in implementing something similar in your mobile app, you should look at something more robust and comprehensive like this jQuery plugin.

Responding to Mobile Touch Gestures

[Recording]

One of the advantages of using HTML5 is the ability to respond to touch gestures like ‘swipe right’, ‘double tap’, ‘pull down’ etc.

    var restAPIClient = new forcetk.Client();
    restAPIClient.setSessionToken('{!$Api.Session_ID}');     

    function enableSwipeRight(){
        // add swipe right event to the list item
        $j('ul li').bind('swiperight', function(e){
            ....
            restAPIClient.del('Merchandise__c',recId, function(success){}, function(error){});
            ....
        });
   }

The JavaScript snippet above shows how you can use jQuery Mobile to bind to some of the more basic touch gestures like ‘swipe right’. Though I didn’t demo or discuss this in detail during the webinar, I’ve implemented a ‘swipe to delete’ function on the Visualforce page that let’s users delete a Merchandise record by swiping right on the list page. The way I delete the Merchandise record in Force.com is also worth highlighting. I’m using the Force.com REST API JavaScript toolkit to make REST API calls (line 8 ) in order to do this. I could have used JavaScript Remoting instead, but I decided to use the JavaScript toolkit to demonstrate another way of accessing/updating Force.com data from a mobile Visualforce page.

Testing and Debugging Mobile Web Apps

[Recording]

During the webinar, I demoed a great debugging tool for web mobile applications – Weinre. You can use Weinre to debug web (Visualforce) pages as they’re being rendered on an actual mobile device (or on an emulator/simulator) and is an invaluable tool for mobile developers. No code to share here – just watch the recording and get further details from the Weinre website.

Using HTML5 Offline Features

[Recording]

One of the more interesting features of HTML5 is the ability to support offline access to your web application. HTML5 has a couple of features that you can use to implement offline access. One is the application cache that allows you to cache static resources locally (like JavaScript and CSS libraries, images, the static page markup). In order to use the application cache, you have to specify a Manifest file to tell the browser what resources you’d like cached locally. Here’s a small snippet from my Visualforce page that shows how you can specific a Manifest file:

<html manifest="/apex/MerchandiseMobileCache">

As you can see, the ‘manifest’ attribute is simply pointing to another Visualforce page. For further details on how to use the application cache, check out this excellent article by my colleague Josh Birk. In that article, you’ll also find pointers on how to use other HTML5 offline features like Web Storage and Web SQL Database to store dynamic data (like a list of Merchandise records).

Another thing that I demoed during the webinar was how to detect when you page has gone offline. Here’s the relevant code:

        //Check online status when the page first loads
        if (!navigator.onLine) {
             //Display an error msg
             return;
        }        

        //If the page goes offline
        $j(window).bind('offline',function(e){
             //Display an error msg
        })

You can check navigator.onLine (caveat: apparently this does not work consistently across all browsers/devices) to determine if the device is currently online. You can also bind to the ‘offline’ event in order to be notified if the device goes offline while the user is viewing your web page.

Developing Hybrid Mobile Applications

[Recording]

The latter half of the webinar was spent on developing hybrid mobile application with the Mobile SDK. Hybrid apps fall somewhere between web and native mobile apps. Like web apps, hybrid mobile apps are developed primarily in web technologies like HTML5, JavaScript, and CSS. However, you can then use the Salesforce Mobile SDK container (which is based on the open source PhoneGap project) to put a thin native ‘wrapper’ around the web application and get some of the benefits of native app development (like the ability to access device functions like the camera, contacts database). For details on how to use the Mobile SDK to convert a web application (whether developed using Visualforce or not) into a hybrid application, check out Tutorials 5 and 6 in the Mobile SDK workbook. For now, I just want to highlight some code that shows how you can access a device function like the camera in a hybrid application.

    function takePic() {
        navigator.camera.getPicture(onPicSuccess, onPicFail, { quality: 50});
    }

    function onPicSuccess(imageData) {
        var recId =  $j('#merchandiseId');
        MerchandiseMobileController.saveMerchandiseImage(imageData, recId,
            function(res,event){
                $j('#merchPic').src = "data:image/jpeg;base64," + imageData;
            });
    }

This is the beauty of the PhoneGap based Mobile SDK container. You can simply use JavaScript to access device features like the camera, microphone, contacts database. In the snippet above, the onPicSuccess callback function gets called once the user is done taking a picture and I then use JavaScript Remoting to send the Base-64 encoded data to Force.com where it gets stored as an Attachment record.

If you’ve made it this far in the post, congratulations (and go get some water!). Apologies for the lengthy post, but hopefully this sample gives you a good starting point for your own mobile adventures. As always, questions and comments are welcome.

 

tagged , , , , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Ariel Techiouba

    Hi,
    In my scenario i’m using “standalone” HTML5 and not VisualForce.

    I’d like to post an image to SFDC, and i’ve built my Apex Rest httppost service.

    The service save an attachment to Account with the image sent, but the attachment is not saved “correctly”:
    If i download and open it with notepad i see different content.

    Has that something to do with base64 / encoding-decoding?
    How can i solve it?
    How can i send the file via JavaScript by letting sf understand it is an image?

    Should i use JavaScript Remoting instead of Apex REST service?

    So many questions.. hope you can help me!

    • Anonymous

      Ariel – I’ve replied to your query regarding binary data in my other blog post concerning Apex REST where you had posted the same question. Let me know if that helps.

  • http://twitter.com/chrisodavies Chris O Davies

    Thanks Sandeep

  • Mahesh Anantharaman

    Let me know if there are some material on OAuth2 and how to enable passcode, expiry of the password etc.. using salesforce

  • http://profile.yahoo.com/JN7XENXGXN7PDNRU2MQ4H6LAW4 jayram

    Hi.
    I am using the SalesForce Mobile Hybrid App for IOS. Can someone please tell me how to implement pinch and zoom functionality within this app?

    Thanks,
    Ram