This is the third in a series of blog posts where I discuss how we built Cloud Hunter – the scavenger hunt mobile app for Dreamforce 2012. The first post covered the basic application use case and architecture and in the second post, I described how we converted a Visualforce-based web version of Cloud Hunter into hybrid Android and iOS applications using the Salesforce Mobile SDK. In this post, I’m going to cover some of the application functionality that we implemented in the hybrid version of Cloud Hunter.

 

Taking a picture

One of the mission types supported by Cloud Hunter is Picture where players have to take a picture of a specific place/person in order to complete the mission. My previous post covered how PhoneGap/Cordova is the critical piece of technology that allows a hybrid app to access device features like the camera via JavaScript. Here’s a small JavaScript snippet from the Mission Visualforce page that shows how PhoneGap can be used to access the device camera.

        function cameraMissionAction(){
            //Invoke the PhoneGap Camera function
            navigator.camera.getPicture(onPicSuccess,
                                        onPicFail,
                                        { quality: 25, destinationType: 0, sourceType: 1});
        }

        function onPicSuccess(imageData) {
            var missionId =  '{!Mission__c.id}';
            $j.mobile.showPageLoadingMsg("a", "Working....", false);

        	//Invoke the JS Remoting function to complete the Picture mission
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.MissionControllerExtension.completeCameraMissionType}',
                imageData,
                missionId,
                '{!gameId}',
                function(res,event){
                    $j.mobile.hidePageLoadingMsg();
                    ...
                });
        }

        function onPicFail(message) {
            showPopupMessage('Error accessing your camera');
        }

Line 3 shows the simplicity and power of PhoneGap. A single line of JavaScript launches the device camera on a Android or iOS device and lets the user take a picture. In the onPicSuccess callback function we’re using a JavaScript Remoting call to send the Base64 encoded image data to Force.com where it is added as an Attachment to the newly created Achievement record. Here’s the corresponding code snippet from the extension class.

    @RemoteAction
    public static Decimal completeCameraMissionType(String imageData,
                                                    String missionId,
                                                    String gameId) {
        //Create a new Achievement record for the Player.
        Achievement__c completedMission = completeMission(gameId, missionId);

        //Add the picture as an Attachment to the Achievement record
        Attachment a = new Attachment (ParentId = completedMission.Id,
                                       Body = EncodingUtil.base64Decode(imageData),
                                       ContentType = 'image/jpg',
                                       Name = 'PhoneImage');
        insert a;
        ....
    }

 

Capturing a signature

Signature mission types require the player to capture the signature of a particular person/luminary on their mobile device. Signature capture is basically just the capture of a user’s touch gestures on a screen. You don’t need PhoneGap or a hybrid application to capture signatures. It can be done entirely in HTML5 using the magical Canvas element. You can of course implement you own custom signature capture widget, but in the spirit of reuse (aka ‘copy and paste’), Cloud Hunter uses a free JQuery plugin called jSignature to implement it’s signature capture. As you can read from the jSignature documentation, that library uses an HTML5 Canvas element to capture a user’s signature as vector outlines of the strokes and returns a high-quality SVG image of the same.

Here’s a JavaScript snippet from the Mission Visualforce page that shows the use of the jSignature library.

 

        $j("#signature").jSignature({color:"#f00", height:150, width:300, bgcolor:"#f5fb92"});
        ...
        function signatureMissionAction(){
            var datapair = $j("#signature").jSignature("getData", "svgbase64");
            var missionId =  '{!Mission__c.id}';
            $j.mobile.showPageLoadingMsg("a", "Working....", false);
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.MissionControllerExtension.completeSignatureMissionType}',
                datapair[1],
                missionId,
                '{!gameId}',
                function(res,event){
                  $j.mobile.hidePageLoadingMsg();
                  ....
                });
        }

The first line of JS code initializes the JSignature library and line 4 returns the user’s signature as a Base64 encoded SVG image. The image is passed to the controller via a JavaScript Remoting call (line 7) where we save the signature image as an Attachment record.

In the final post of this series, I’ve cover how Cloud Hunter implemented check-ins (i.e. Geolocation) and Bar/QR code scanning.

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