Building Client / Cloud Apps with Flash Builder for Force.com

I have a theory. The majority of people who use enterprise software today use old school Client / Server apps. We’ve been trying to move these apps to the web for more than ten years. The ease of deployment of web apps is a clear motivator. Yet the client capabilities of the plain old web browser have not been sufficient for many apps to make the leap. This is why I love Flex and the Flash Platform. It provides a way to use web technologies and the web deployment model but adds many of the critical things needed for mission critical apps that people use all day long.

But no one wants to go back to the Client / Server architecture. We want to embrace Cloud Computing architectures but not lose the client capabilities. What we really need is the Client / Cloud architecture. We need a web deployment model that provides ease of deployment but also the ability to install applications on our desktops and mobile devices.

This is why I’m so excited about the new Adobe Flash Builder for Force.com. In a nutshell this is a tool that Adobe and Salesforce.com built together to enable developers to build great software using Flex for the UI and Force.com for the Cloud back-end. It’s a wonderful combination of technologies that will help many Client / Server apps make the switch to Client / Cloud.

Applications created with Flash Builder for Force.com can be run in the browser, on the desktop, and on mobile devices. These applications can be assembled from the hundreds of Flex components that are out there (check out many of them in Tour de Flex).

Check out this video to see how to use Flash Builder for Force.com to build a simple app:

As you can see, it’s very easy to get started. But I wanted to go a step further and try to build something real–something that shows a genuine use case for extending beyond the out-of-the-box Salesforce.com UI. I wanted to keep it really simple so that I could post the code here. What I came up with is this (in user story form):

  • As a Salesforce.com user I want to take a photo, using my phone, of one of my contacts so that the photo can be saved to their contact record for future reference.
  • As a Salesforce.com user I want to see photos I’ve taken of my contacts so that I can be reminded of what they look like.

Simple enough. So here is what I came up with:

To build these two apps I first downloaded and installed Flash Builder for Force.com. I used the Adobe AIR for Android prerelease to build the mobile app. Here is how I created these apps.

First I added a new field to Contact to store the photo. Salesforce.com doesn’t have a binary field so I used a large text field (32k limit). I’ll store the photo Base64 encoded.

Then in Salesforce.com I saved my enterprise.wsdl file. Check out a great video from Dave Carroll to see how to do this.

Now in Flash Builder for Force.com I created a new Force.com Flex Project for the mobile app. If you do this on your own and want to run on a mobile device then you will need to overlay the AIR for Android SDK on top of a Flex 4.1 SDK. Select Desktop Application as the app type. Replace WindowedApplication with just Application. And replace the F3DesktopApplication with F3WebApplication since F3DesktopApplication uses APIs that are not available on AIR for Android. (BTW: Flash Builder, Flex, and Force.com Flex Projects do not officially support mobile deployment yet. It works but there is no support and no guarantees.) If you are building a standard Web Application or Desktop Application then you can just leave the generated code as is.

Using the Data/Services wizard I connected to Salesforce.com using my enterprise.wsdl file. After the services and value objects have been generated I modified the Contact object and added a Bindable account property. The generated application already included the F3DesktopApplication Declaration used to connect to Salesforce. Due to an incompatibility with that API and AIR for Android I switched it to use F3WebApplication. In F3WebApplication’s loginComplete event handler I query Salesforce.com for Accounts and then Contacts, associate contacts with their account, and then store the contacts:

app.wrapper.query("select Id, Name from Account", new AsyncResponder(function(data:ArrayCollection, token:Object):void {
    accounts = data;
    app.wrapper.query("select Id, AccountId, FirstName, LastName, Phone, MobilePhone, Email, Title, Department, MailingCity, photoData__c from Contact", new AsyncResponder(function(data:ArrayCollection, token:Object):void {
        for each (var contact:Contact in data)
        {
            for each (var account:Account in accounts)
            {
                if (account.Id == contact.AccountId)
                {
                    contact.account = account;						
                }
            }
        }
        contacts = data;
    }, handleError));
}, handleError));

Notice in the query that I’m fetching photoData__c, which is the custom field I created on Contact to store the photo.

In the renderer for a contact I need to either display the photo if there is one or let the user add one. Here is the simple UI code to handle that:

<s:Group width="92" height="92" top="8" right="8">
    <s:Rect width="92" height="92">
        <s:fill>
            <s:SolidColor color="#cccccc"/>
        </s:fill>
    </s:Rect>
    <s:Label id="addPhoto" text="Add a photo" width="92" height="92" verticalAlign="middle" textAlign="center"/>
    <s:BitmapImage id="photo" width="92" height="92"/>
</s:Group>

When the contact is set I check to see if there is a photo and if so display it:

if (contact.photoData__c == null)
{
    photo.visible = false;
    return;
}
 
var decoder:Base64Decoder = new Base64Decoder();
decoder.decode(contact.photoData__c);
 
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void {
    photo.source = event.target.content;
    photo.visible = true;
});
loader.loadBytes(decoder.toByteArray());

The data from the photoData__c field is Base64 decoded and then displayed using the Flex BitmapImage component.

Now when the user clicks on the photo or empty photo box I use the AIR for Android CameraUI to grab a photo, resize it, covert it to a PNG, Base64 encode it, set it on the contact, and then save the contact to Salesforce.com:

if (CameraUI.isSupported)
{
    cameraUI = new CameraUI();
    cameraUI.addEventListener(MediaEvent.COMPLETE, function(event:MediaEvent):void {
        var loader:Loader = new Loader();
        loader.load(new URLRequest(event.data.file.url));
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void {
            var bitmap:Bitmap = event.target.content as Bitmap;
 
            var result:BitmapData = new BitmapData(46, 46, false);
            var matrix:Matrix = new Matrix();
            matrix.scale(46 / bitmap.width, 46 / bitmap.height);
            result.draw(bitmap, matrix);
 
            var pngEncoder:PNGEncoder = new PNGEncoder();
            var pngBytes:ByteArray = pngEncoder.encode(result);
 
            var base64Encoder:Base64Encoder = new Base64Encoder();
            base64Encoder.encodeBytes(pngBytes);
            var encodedImage:String = base64Encoder.flush();
 
            contact.photoData__c = encodedImage;
 
            displayPhoto();
 
            F3WebApplication.getInstance().wrapper.save(contact, new AsyncResponder(function(data:Object, token:Object=null):void {
            }, FlexGlobals.topLevelApplication.handleError));
        });
    });
    cameraUI.addEventListener(ErrorEvent.ERROR, function(event:ErrorEvent):void {
        FlexGlobals.topLevelApplication.handleError(event);
    });
    cameraUI.launch(MediaType.IMAGE);
}

That’s it for the mobile app! I compiled it, exported it to an Android app, and then copied it to my phone. Pretty simple and as you can see it works! One limitation with my approach is the 32k limit of the photoData__c field. However, I think I could easily get around that by striping the Base64 encoded data across multiple fields. It’s not ideal but it would work.

To display the photo when I view a contact on Salesforce.com I created a very simple Flex app using another Force.com Flex Project. I could have also added photo upload to this application but chose to keep it simple. All it does is display the selected contact’s photo. Here is the complete code (after generating the required services in Flash Builder):

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:flexforforce="http://flexforforce.salesforce.com">
 
    <fx:Script>		
    import mx.rpc.AsyncResponder;
    import mx.utils.Base64Decoder;
    </fx:Script>
 
    <fx:Declarations>
        <flexforforce:F3WebApplication id="app" requiredTypes="Contact">
            <flexforforce:loginComplete>
                app.wrapper.query("select photoData__c from Contact where Id = '" + this.parameters.contactId + "'", new AsyncResponder(function(data:Object, token:Object):void {
                    if (data.length == 1)
                    {
                        if (data[0].photoData__c == null)
                        {
                            photo.visible = false;
                            noPhoto.visible = true;
                            return;
                        }
 
                        var decoder:Base64Decoder = new Base64Decoder();
                        decoder.decode(data[0].photoData__c);
 
                        var loader:Loader = new Loader();
                        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void {
                            photo.source = event.target.content;
                            photo.visible = true;
                        });
                        loader.loadBytes(decoder.toByteArray());
                    }
                }, function(fault:Object):void {
                    // ignored
                }));
            </flexforforce:loginComplete>
        </flexforforce:F3WebApplication>
    </fx:Declarations>
 
    <s:applicationComplete>
        app.serverUrl = this.parameters.serverUrl;
        app.loginBySessionId(this.parameters.sessionId);
    </s:applicationComplete>
 
    <s:Rect width="92" height="92">
        <s:fill>
            <s:SolidColor color="#cccccc"/>
        </s:fill>
    </s:Rect>
 
    <s:Label id="noPhoto" text="No Photo" width="92" height="92" textAlign="center" verticalAlign="middle" visible="false"/>
 
    <s:BitmapImage id="photo" width="92" height="92"/>
 
</s:Application>

Finally I created a custom S-Control to run the Flex app:

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="ContactPhoto" width="92" height="92" 
codebase="https://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> 
    <param name="movie" value="{!Scontrol.JavaArchive}" /> 
    <param name="flashvars" value="sessionId={!API.Session_ID}&serverUrl={!API.Partner_Server_URL_90}&contactId={!Contact.Id}" /> 
    <embed src="{!Scontrol.JavaArchive}" width="92" height="92" name="ContactPhoto" 
flashvars="sessionId={!API.Session_ID}&serverUrl={!API.Partner_Server_URL_90}&contactId={!Contact.Id}" 
type="application/x-shockwave-flash" 
pluginspage="http://www.adobe.com/go/getflashplayer"> 
    </embed> 
</object>

I uploaded the compiled Flex app to the S-Control and added it to the Contact page. And that’s it! In just a few hours I extended Force.com and built a cool mobile app. I could also have easily created a desktop widget for browsing contacts and adding photos. If you are looking for a fun project to use as a way to learn this stuff that would be a good one! :)

Here are some resources to help you get started with Flash Builder for Force.com:

Have fun building the next generation of software! Let me know how it goes.

Developing Mobile Flash / Flex – Scaling and Zooming

Mobile development with Flash and Flex is a new frontier, full of new adventures and discoveries. Recently I discovered something that might be useful to you. By default the mobile web browser on my Android 2.2 device scales a web page to make more room to display pages typically built for a desktop profile. Here is what a little test mobile Flex app I built looks like:

Strange! The width and height are larger than the screen resolution. You can fix this by adding the following to the HTML page:

<meta name="viewport" content="target-densityDpi=device-dpi; user-scalable=0;" />

And now it will look like:

Now that looks right! This also turns off the two-finger / pinch zooming feature for the page (which is more important for content that hasn’t been optimized for a mobile profile).

I hope this is useful for those of you embarking on new adventures with Flash / Flex on mobile devices!

Flash Platform and Salesforce.com Webinar and Mobile App

Client + Cloud technologies have been quickly evolving and maturing. The combination of Flex and Salesforce.com continue to lead the way for next generation Client + Cloud applications. Recently I did a Webinar on The Flash Platform and Salesforce.com with Dave Carroll from Salesforce. If you missed it you can watch the recording to see how you can begin developing Client + Cloud apps. Also watch Jeff Douglas demo an offline case management app he built with Flex and Force.com. Awesome stuff!

Last week I was able to spend a few hours with Model Metrics porting their Pharma2GO Adobe AIR app to run on an Android Mobile device. Using the AIR for Android Prerelease we quickly created a mobile friendly UI with Flex and reused the same data sync code from the desktop app. Check out the end result:

Listen to what Model Metrics had to say about this in their blog “HTML 5 – Ready for Primetime in the Enterprise?“:

One of our early iPhone products on the iTunes AppStore was Search2GO, a simple search tool for Salesforce.com. This was built in Objective C and it took approximately 8 weeks to develop. Yesterday I watched two developers create over half of this same functionality using Flex/AIR and had it running on an Android phone in a day. Granted there are still things that could be added, but this was a great illustration of why Flex/AIR is a great toolset.

These are exciting times for Client + Cloud apps now that the “Client” can easily be on the web, desktop, and mobile device using the same technologies and tools!

Flex on Android in Flash Player and AIR

This week at the Google I/O conference Adobe announced that a Flash Player 10.1 beta and an Adobe AIR prerelease are now available for Android devices. This is really exciting news for those of us building apps on the Flash Platform because now we can begin building apps in Flex for these mobile devices (and many others coming soon).

Take a look a some of the quick demos I’ve built with Flex running on Android in Flash Player and AIR:

You can get the source code for all of these demos from github.

Also Christophe Coenraets has posted some great Flex mobile demos. Check out his Employee Directory and Stock Trader demos.

These are very exciting times for developers!

If you want to check out the Flash Player 10.1 beta for Android it will be available in the Android Marketplace for Android 2.2 devices. You can try Adobe AIR for Android today by signing up for the prerelease.

Flex Performance on Mobile Devices

This past weekend I spent an hour optimizing the Flex 4 scrolling demo that I posted last week. The original demo was intended to show how to hook up touch events to the Flex 4 List / DataGroup controls. This new version adds some optimizations for the touch event handling and adds the kinetic flick behavior. Check it out and let me know what you think:

I’ve posted the code for this second version of the touch scrolling demo. It was pretty trivial to optimize it this far. With a little more work it’ll be as smooth as silk and as fast as Apolo Ohno. :)

Over the past few days I’ve received some questions about the performance of Flex apps on mobile devices. My Census RIA Benchmark has been a great way to compare the performance of various data loading techniques and technologies. Now that I have my Android based Nexus One mobile device with an early build of Flash Player 10.1 I wanted to see how fast I could load and render large amounts of data in a Flex application. I’m really impressed with the results! 20,000 rows of data loaded from the server and rendered on my phone in about 2 seconds! Those 20,000 rows can then be sorted on the device instantaneously. Pretty amazing performance for such a little device! Check out the video:

You can run the mobile version of the Flex AMF Census Test and check out the source code. Let me know what you think.

Flex 4 List Scrolling on Android with Flash Player 10.1

UPDATE 1: The first version of this demo was intended to show how to hook up touch events to the Flex 4 List / DataGroup controls. I’ve posted a new version that adds some optimizations for the touch event handling and adds the kinetic flick behavior.

One of the challenges of running existing web content on mobile devices is that user interactions differ between mediums. For instance, on a normal computer with a mouse, scrolling though lists is often done by clicking on scroll bars or mouse wheels. On mobile devices that lack a pointing device this is not the best interaction paradigm. On devices with touch screens the paradigm for scrolling is usually a swipe gesture.

In Flash Player 10.1 there are APIs for gestures and multitouch events. I thought it would be fun to hook up the list scrolling on a Flex 4 List to the TouchEvent on my Nexus One. Check out the video:

If you want to see how I created this simple demo, check out the source code. Let me know if you have any questions.

Flex Apps on Mobile Devices

This week at Mobile World Congress Adobe has been showing off Flash Player 10.1 on a variety of mobile devices. Last week I received Google’s Nexus One device with an early version of Flash Player 10.1 on it. Here is a video I shot today showing how Flex applications can run on mobile devices with Flash Player 10.1 and how existing applications can be tweaked for the size constraints of these devices. Let me know what you think.

BTW: The app I created for the demo is available at bit.ly/tdfmdb.

The Open Web: Now Sexier and Smaller

In the past Open Web proponents have criticized Flash and Flex because the SWF specification – while being published and publicly available – limited what readers could do with the specification. More specifically the agreement to view the specification required that readers not build programs that would run SWF files. The intentions behind this were good – Adobe does not want Flash to have inconsistent and incompatible implementations.

Today Adobe Systems has announced that they are removing those restrictions on the SWF and FLV specifications! This is very exciting news and something I’ve been lobbying for since I started working for Macromedia (actually I think I began bugging Emmy Huang about this before I started working for Macromedia). Flash has become the standard for sexier web experiences with RIAs, video on the web, and interactive web content. Today that standard is truly open!

Adobe has also announced the Open Screen Project which aims to create an open and consistent layer on top of the countless small device platforms including consumer devices, phones, MIDs, and set top boxes. This is an extremely exciting project that will hopefully do for the world of small devices what the browser did for the PC world. You could also call this the “RIA Everywhere!” project. :)

Software keeps getting more exciting and the Open Web just got sexier and smaller!