Mobile SDK Workbook

uglyveinInternet και Εφαρμογές Web

24 Ιουν 2012 (πριν από 5 χρόνια)

998 εμφανίσεις

Mobile SDK Workbook
Build iOS, Android and HTML5 Applications
Quick 30-Minute Tutorials
08_30_2011_v1
Go to http://developer.force.com/workbooks for more workbooks.
Workbook-Mobile.indd 1
8/19/11 3:50 PM

1

About the Mobile Workbook..........................................................................................................................................2

Three Approaches to Building Mobile Applications.........................................................................................2

About the Mobile SDK (Developer Preview)...................................................................................................2

Choosing a Back End: Force.com or Database.com..........................................................................................2

Before You Begin..............................................................................................................................................3

Tutorial 1: Setting Up the Back End Database...............................................................................................................4

Prerequisites.......................................................................................................................................................4

Step 1: Understand the Data Structure...............................................................................................................4

Step 2: Create the Schema.................................................................................................................................4

Step 3: Upload Data...........................................................................................................................................5

Step 4: Configure OAuth...................................................................................................................................5

Step 5: Exploring the REST API.......................................................................................................................6

Summary............................................................................................................................................................8

Tutorial 2: Creating an iOS Application.........................................................................................................................9

Prerequisites.......................................................................................................................................................9

Step 1: Create an Application Using The Template..........................................................................................9

Step 2: Run Your Application.........................................................................................................................10

Step 3: Putting It All Together.........................................................................................................................12

Summary..........................................................................................................................................................14

Tutorial 3: Creating an Android Application................................................................................................................15

Prerequisites.....................................................................................................................................................15

Step 1: Download the Cloud Tunes Project and Mobile SDK........................................................................15

Step 2: Create an Android Project in Eclipse..................................................................................................15

Step 3: Import the Mobile SDK library...........................................................................................................16

Step 4: Add OAuth Authentication Logic.......................................................................................................17

Step 5: Query and List Albums.......................................................................................................................19

Step 6: Query and List Tracks.........................................................................................................................21

Step 7: Putting It All Together.........................................................................................................................21

Summary..........................................................................................................................................................23

Tutorial 4: Creating an HTML5 Application................................................................................................................24

Prerequisites.....................................................................................................................................................24

Step 1: Download Sample Application............................................................................................................24

Step 2: Setup OAuth........................................................................................................................................25

Step 3: Retrieving and Displaying Albums.....................................................................................................26

Step 4: Retrieving and Displaying Tracks.......................................................................................................28

Step 5: Putting It All Together.........................................................................................................................29

Tutorial 5: Creating an iOS Container Application......................................................................................................31

Prerequisites.....................................................................................................................................................31

Step 1: Download the Container Sample Application.....................................................................................31

Step 2: Add the HTML5 Application to the Container...................................................................................31

Step 3: Add your OAuth Consumer Key.........................................................................................................31

Step 4: Update login.js.....................................................................................................................................32

Step 6: Compile and test..................................................................................................................................33

Step 7: Putting It All Together.........................................................................................................................34

Summary..........................................................................................................................................................34

Next Steps.....................................................................................................................................................................35


2

About the Mobile Workbook
A staggering number of people are using mobile devices, from phones to tablets, to access application data. As a
developer, you need to create applications that cater for these mobile devices. This workbook shows three
approaches to building such applications that access data on Force.com and Database.com.
Three Approaches to Building Mobile Applications
There are 3 approaches to building mobile applications covered in this workbook:

!
Native applications are coded using a platform's native capabilities. In this workbook, we show how to
construct native applications for iOS and Android.
!
HTML5 applications are lightweight server-side pages built using HTML5, CSS and JavaScript. These
applications typically offer the most portability, albeit with less of a native look and feel. This workbook
shows how to create an HTML5 application.
!
Hybrid applications merge the portability of the HTML5 applications with native device capabilities by
providing HTML5 applications access to native capabilities, such as the camera or address book, through a
JavaScript bridge in a native application container. This workbook shows how to create an iOS hybrid
application.
About the Mobile SDK (Developer Preview)
The Salesforce Mobile SDK is an open source suite of developer technologies that simplify the development of
mobile applications.

The Force.com and Database.com platforms use standard OAuth 2.0, and an open REST API - so you can simply
code straight against these. The Mobile SDK adds additional value by a) providing native OAuth implementations
for Android and iOS that work out-of-the-box b) providing OAuth access token management, including persistence
and refresh capabilities c) providing both native wrappers for building native applications, as well as containers for
building hybrid applications.

This workbook uses a developer preview release of the Mobile SDK. As such, the SDK may change over the
coming months.

Tip: You can find the latest version of this workbook at developer.force.com/workbooks
and the latest Mobile SDK
at developer.force.com/mobile
.
Choosing a Back End: Force.com or Database.com
The mobile applications that you build in this workbook will work whether you store your data on a Force.com
Developer Edition or Database.com Sandbox. Both Force.com and Database.com have a REST API and OAuth 2.0
- which are the main back-end technologies used in the workbook.

While the workbook assumes you are using a Force.com Developer Edition, and uses Force.com login end points
such as login.salesforce.com, you can simply substitute your Database.com credentials and end point, such as
test.database.com, to get it working there.

3

Before You Begin
This workbook assumes you are somewhat familiar with developing on the various platforms and technologies, and
with development on Force.com and Database.com. We do try and make it easy where we can, by supplying
applications you can easily download and execute.

All of the prerequisites are listed in the appropriate tutorials, but it's important to know that:
!
To build the iOS applications, you'll need OS X and Xcode
!
To build the Android application, you'll need the Android SDK
!
To build the hybrid application, you'll need a server from which to serve HTML and JavaScript pages

4

Tutorial 1: Setting Up the Back End Database
The tutorials in this workbook build mobile applications that access data in the cloud. The applications first
authenticate using OAuth 2.0, and then access the data using a REST API by issuing standard HTTP verbs.
This tutorial lays the groundwork by creating a schema for the database, loading it with data, and configuring OAuth
for the mobile clients. You can use either Force.com or Database.com.
Prerequisites
You need a Force.com Developer Edition or Database.com account. You can grab a free account at either
http://developer.force.com/join
or http://www.database.com/
.
Step 1: Understand the Data Structure
The schema used in this workbook is for the management of albums and tracks in an online music business. It's got
the bare essentials - just two objects: Album and Track. The Track object is in a master-detail relationship with the
Album object. For reference, here are the custom fields in each object.
The Album object has: a standard name field, Name, of type Text, a Description field, of type Long Text Area, a
Released On field, of type Date, and a roll-up summary field, summing the Price field of Track:
The Track object has: a standard name field, Name, of type Text, a Price field, of type Currency (5, 2), and a master-
detail relationship to Album:
It's a simple data model that allows us to list tracks within albums, the price of individual tracks, and aggregate the
prices of tracks to create a price for the albums.
Step 2: Create the Schema
You can create the schema yourself, using the description of the objects in Step 1, but we recommend using the
Workbench tool so that you have an identical schema implemented, and data loaded:
!
If you're using Force.com Developer Edition, download the schema ZIP from
http://media.developerforce.com/workbooks/mobile/schemaDE.zip

If you're using Database.com, download the schema ZIP from
http://media.developerforce.com/workbooks/mobile/schema.zip

!
Navigate to the Workbench at https://workbench.developerforce.com
/
!
Log in using your Force.com or Database.com credentials
!
Click Migration -> Deploy
!
Click Choose File, and select the downloaded ZIP file
!
Enable Single Package and Rollback on Error
5

!
Click Next, and then Deploy
That's it! The schema described in Step 1 is now deployed to your environment. On Database.com, you can explore
it by navigating to App Setup -> Create -> Objects. On Force.com, click on your name, then Setup -> App Setup ->
Create -> Objects.
Step 3: Upload Data
We'd like your mobile applications to display some real data. Continue using the Workbench to upload a data set:
!
Download the data set from http://media.developerforce.com/workbooks/mobile/data.txt

!
In Workbench, click Utilities -> Apex Execute
!
Paste in the contents of the downloaded data.txt file
!
Click Execute
The data.txt file contains Apex calls that first delete any existing records in the Album and Track objects, and
then repopulate those albums with choice album and track data.
Step 4: Configure OAuth
You are going to have users authenticating on the mobile device before allowing them access to the data.
Database.com and Force.com support OAuth 2.0 as an authentication mechanism. With OAuth 2.0, a client
application delegates the authentication to a provider, in this case Force.com or Database.com, which in turn issues
an access token if the user successfully authenticates.
As a result, your application doesn't need to handle authentication explicitly; it simply needs to ensure that a valid
access token accompanies all interactions with the API. You can typically download an OAuth 2.0 library to do the
heavy lifting. The tutorials in this workbook use the Mobile SDK, which includes an OAuth 2.0 implementation.
Before an application can use OAuth2.0, you have to configure your environment. Log in to your Force.com or
Database.com instance as an administrator and configure a remote access application:
!
Navigate to App Setup -> Develop -> Remote Access
!
Click New
!
For Application, enter "Test Client"
!
For Callback URL, enter sfdc://success
!
For Email, enter your email address
!
Click Save


6

The detail page for your remote access configuration will display a consumer key as well as a consumer secret
(which you have to click to reveal). You'll need these in later tutorials.

If you're familiar with OAuth, you'll understand that the callback URL is traditionally the URL that a user's browser
is redirected to after a successful authentication transaction. For mobile applications, the Callback URL means
something subtly different. Native application on a mobile device can't be redirected to a URL (you're building an
application, not a browser). So instead, the callback URL can be thought of as a signal. If, during the OAuth dance,
the callback URL is sent to the mobile application, then the application can detect that it's successfully
authenticated.
Step 5: Exploring the REST API
Let's quickly explore the REST API using Workbench. This will give you a feel for some of the method calls in the
REST API and their return values, and help make sense of the calls made in the following tutorials.

!
Go to Workbench at https://workbench.developerforce.com/
, and log in again if needed.
!
Click utilities -> REST Explorer

Because we're using a REST API to access the database, accessing and manipulating data is simply a matter of
manipulating URLs, and using standard HTTP verbs like GET, POST and DELETE. All of the URLs start with
/services/data/, followed by a version number, followed by a path to the resource.

The exact format of the URLs is described in the REST API Developer's Guide
, but the following examples will
give you a feel for them.

!
In the text area, enter the following text:
/services/data/v22.0/query/?q=SELECT id, name, price__c FROM album__c
!
Ensure GET is selected, click Execute, and then click Show Raw Response

The REST API call (to the query resource, with the query set as a parameter) returns a list of the albums in your
database (in this case in the JSON format):
{
"totalSize": 5,
"done": true,
"records": [
{
"attributes": {
"type": "Album__c",
"url": "/services/data/v22.0/sobjects/Album__c/a003000000HAHSGAA5"
},
"Id": "a003000000HAHSGAA5",
"Name": "Help!",
"Price__c": 10.29
},
….....
]
}

Note how this list returns the albums within a records element, embedded in the response. The response also
contains the ID of each record. For example, in the above output, the Help! album has an ID of
a003000000HAHSGAA5. It also, helpfully, provides the REST URL needed for retrieving the contents of a
particular record:


7

!
In the text area, enter the value of the url attribute. In our case, it was something like this:
/services/data/v22.0/sobjects/Album__c/a003000000HAHSGAA5
!
Click Execute, and Show Raw Response.

The server will respond with the details of the album resource, something like this:
{
"attributes": {
"type": "Album__c",
"url": "/services/data/v22.0/sobjects/Album__c/a003000000HAHSGAA5"
},
"Id": "a003000000HAHSGAA5",
"OwnerId": "00530000004qf3jAAA",
"IsDeleted": false,
"Name": "Help!",
"CreatedDate": "2011-08-12T10:44:29.000+0000",
"CreatedById": "00530000004qf3jAAA",
"LastModifiedDate": "2011-08-12T10:44:29.000+0000",
"LastModifiedById": "00530000004qf3jAAA",
"SystemModstamp": "2011-08-12T10:44:29.000+0000",
"Description__c": "North American release",
"Released_On__c": "1965-08-06",
"Price__c": 10.29
}

This result contains a few attributes describing the record, all your custom fields, as well as a number of system
fields.

Note the form of the URL - in this case the resource, album__c, is there in the URL - that's the API name of the
Album object you created earlier. So a GET to /services/data/v22.0/sobjects/<Object Type
Name>/<ID> returns the record of the given identifier and object. In fact, a DELETE to the same URL, will delete
the record. And a POST to /services/data/v22.0/sobjects/Album__c/ (with the correct body) will
create a new record.

There are two important elements of interacting with the REST API that are masked in the above interactions:
!
Every HTTP request has a header element, Authorization, which contains an access token. The
access token was returned as part of logging in to your environment.
!
Every HTTP request must be made to a base URL - the URL of the Force.com or Database.com instance.
This URL is also returned as part of the OAuth authentication process.

You can find these two pieces of data in Workbench:
!
Navigate to Info -> Session Information, and expand Connection

Our Endpoint value starts with https://na1.salesforce.com/services
- that's where our HTTP requests are being sent.
Your endpoint may well be different. The Session Id contains the access token.

If you dig deep enough into the code in the following tutorials, you will always find that building applications on the
mobile devices contains these elements - the OAuth dance, the retrieval of the instance URL and access token - and
the use of these in all subsequent interactions with the REST API.

8

Summary
In this tutorial you used a tool to upload a data schema describing the Album and Track objects, as well as data.
You also configured OAuth for you environment, and learned that interacting with the REST API is simply a matter
of using the appropriate HTTP verb on the appropriate resource URL.

That should be enough to get you started! You now have a database, a REST API, and OAuth configured. Let's
press on and create a few mobile applications that access the data.


9

Tutorial 2: Creating an iOS Application
In this tutorial you create and configure an iOS application that accesses the album and track data that you created in
Tutorial 1
. The application can run in the Xcode simulator, and can also be deployed to your iPhone or iPad device.

Building an entire iOS application from scratch is certainly possible, but typically you'd use libraries to do some
heavy lifting for you. This tutorial installs an Xcode project template, which creates most of the basic elements of
the application, and which includes a developer preview of the Mobile SDK. Feel free to make changes to the code
and experiment.
Prerequisites
Working on your own computer:
!
You need to have Xcode 4.02 installed
!
You need to have completed Tutorial 1

!
You need to install the Xcode Project Template
"
Shut down Xcode if you have it running
"
Go to developer.force.com/workbooks
, navigate to the Mobile Workbook, and download the
Mobile Workbook Xcode template
"
Double click on the installer, and follow the instructions, accepting the defaults
Working on a lab computer:
!
Xcode and the Xcode Template are already installed
!
You need to have completed Tutorial 1

Step 1: Create an Application Using The Template
The Xcode Mobile Workbook Template makes it easy to create new iOS projects. Let's use it. This involves using
the template to generate the application, and then configuring it to use a few native libraries.
1.
Start up Xcode and create a new project. Either click on "Create a new Xcode project", or click on File,
New, New Project.
2.
You'll be presented with a pallet of templates. Select Mobile-SDK-based Application and click Next.
3.
You'll now be asked to fill in a few options to configure the project:
!
For Product Name, enter some name (your own) to identify your application without any
spaces, or special characters.
!
For Company Name enter your company name, usually the same as your domain name without
the .com extension. Enter mbworkbook
!
For Consumer Key enter the OAuth Key you found in Tutorial 1
Step 4.
!
For Redirect URL enter the same URL as Tutorial 1
Step 4: sfdc://success This is what
you remote access configuration is already set to use.
!
For Login URL, enter the login endpoint. This will typically be login.salesforce.com.
Do not include the https:// prefix.
!
The Beginning SOQL Statement is used to pre-configure the query that the application
will execute. Enter: select Id, Name from Album__c
!
The SOQL Field to Display lets you choose which of the values returned from the query
will be displayed in the app. Enter Name. Note: case is important here. Fields will be returned
from Force.com in true case.

10


4.
Click Next, select a directory in which to store your application, and then Create.
Congratulations - you now have a complete iOS application. It's not quite working yet though. Click Command-B
and you'll see a few linking issues. Let's fix those now.
1.
Click on the Build Settings tab.
2.
Click All
3.
In the search field, enter Other Linker Flags
4.
Double-click on the Other Linker Flags row, under the Yes column. In the box that pops up, add a
new flag -all_load. Click Done.
5.
Now click on the Build Phases tab. Expand the Link Binary With Libraries box, and click + in that
section.
6.
In the search box, type libxml2. Select libxml2.dylib, and click Add.

What this does is ensure that the project uses the correct XML parser.
That's it, your application is configured.
Step 2: Run Your Application
You're ready to test it out.
!
Hit Command-R. Your application will run in the iOS simulator. On start up, the application will start the
OAuth authentication flow, which will result in a web page being shown from Force.com that invites you to
authenticate (shown on the left in the figure below).
!
Enter your credentials, and click Login.
11

!
You now have to explicitly grant the application permission to access your database. Click Allow (shown
on the right in the figure below).


The application then performs a query of album records from the database, and displays them in a table.


12

To deploy the application to an actual device, you'll need to configure your device to work with Xcode. For the lab
machines and devices:
1.
Click your project in the Project Navigator (the top-most node).
2.
Select your app from the TARGETS list.
3.
Click Summary.
4.
Select Universal from the Devices picklist.
5.
Click Build Settings.
6.
In the search box, enter Code Signing Identify.
7.
Select IPhone Developer from the picklist.
8.
From the Scheme selector, choose the DevZone iPad
9.
Click Command-R. Your app will now be deployed to the tethered iPad.

Step 3: Putting It All Together
The iOS application you created follows a fairly standard pattern of application construction on iOS. Here's a quick
run down of the interesting bits, calling out the interactions with the REST API along the way. Follow along by
opening each file in Xcode to view the complete source.

Dependencies
The Dependencies folder lists a number of libraries used in the application. We're using:
!
SBJson to perform JSON parsing of the results returned from the REST API.
!
RESTKit as a way of simplifying the interactions with the REST API.
!
SalesforceSDK as the main Objective-C interface to the API. Check out the SFRestAPI.h header
file to see the calls and examples of how to use them.
!
SalesforceOAuth as an implementation of OAuth 2.0 in Objective-C.

AppDelegate.m
The AppDelegate.m class is one of the main entry points in the application, and orchestrates the application.
Let's step through the important bits.

The standard lifecycle method applicationDidBecomeActive: gets called when your application is active,
and this kicks off a call to login.

The login method starts the OAuth work flow. Note how it uses constants defined at the beginning of the
AppDelegate class - remoteAccessConsumerKey, OAuthRedirectURI and OAuthLoginDomain.
These are prepopulated with the values you entered when creating the application - feel free to change them to a
different Force.com instance.

After configuring a credential object with these data, this method configures an instance of
SFOAuthCoordinator. This object will ultimately cause the OAuth window to pop up.

self.coordinator = [[[SFOAuthCoordinator alloc] initWithCredentials:credentials]
autorelease];
self.coordinator.delegate = self;
[self.coordinator authenticate];

The coordinator works by invoking methods on a delegate at certain points in the authentication lifecycle. The above
code specifies that the AppDelegate instance is also the delegate (in fact, you'll see that the interface for
AppDelegate implements SFOAuthCoordinatorDelegate.

The SFOAuthCoordinateDelegate methods are straightforward. Here's the one invoked on a successful
authentication:
- (void)oauthCoordinatorDidAuthenticate:

13

(SFOAuthCoordinator *)coordinator {
[coordinator.view removeFromSuperview];
[self loggedIn];
}

This removes the view used for authentication, and then calls loggedIn. At this point, you have authenticated
against your instance. So, on to loggedIn!

- (void)loggedIn {
[SFRestAPI APIWithCoordinator:self.coordinator];
[SFRestAPI sharedInstance].apiVersion = @"v22.0";
self.window.rootViewController = [[[RootViewController alloc]
initWithNibName:@"RootViewController" bundle:nil] autorelease];
}

This method sets up an instance of SFRestAPI with the coordinator, which is now authenticated, and creates a root
view controller. At this point, you can use SFRestAPI to make REST API calls. The view controller used in this
project is a UITableViewController, and you can find its implementation in RootViewController.m.

RootViewController.m.
This is a standard iOS table view controller, but the magic happens in the viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Database-iOS";

SFRestRequest *request;
request = [[SFRestAPI sharedInstance]
requestForQuery:@"select Id, Name from Album__c"];

[[SFRestAPI sharedInstance] send:request delegate:self];
}

This method uses the SFRestAPI shared instance, already configured in the loggedIn method, to construct a
request to the REST API query URL. Note that self is used as a delegate, and as a result the request:
didLoadResponse: method will be invoked when the data is returned from the API call:

- (void)request:(SFRestRequest *)request didLoadResponse:(id)response {
self.dataRows = [response objectForKey:@"records"];
[tableView reloadData];
}

This method is invoked with the response, already parsed. The response parameter (see Tutorial 1
) is an
NSDictionary object that follows the structure of the returned JSON. The method extracts the object (another
dictionary) associated with the records key, assigns it to the data that backs the table view, and then calls
reloadData on the view - which will display the records.

While there are many methods and classes, typical of an iOS project, the basic architecture of the application is
straightforward:
!
The authentication view is loaded soon after the application starts.
!
The authentication object, SFOAuthCoordinator, invokes callbacks in a delegate, which you have to
implement.
!
On successful authentication, you can create an instance of SFRestAPI, which then serves as your main
conduit to the REST API.

There are many more methods on SFRestAPI - feel free to explore and modify the application to retrieve and
manipulate other data.

14

Summary
In this tutorial you learned how to create an iOS application that retrieved data from Force.com. The tutorial made
use of a project template that enables you to easily create new iOS projects that already have the necessary
dependencies installed. The Mobile SDK provides wrappers around the underlying REST API, making OAuth
painless, and seamlessly ensuring that OAuth access tokens are sent on all API calls.

15

Tutorial 3: Creating an Android Application
In this tutorial you create and configure an Android application that accesses the album and track data created in
Tutorial 1
. The application can run in the Android Emulator, and can also be deployed to an Android device for
testing purposes.
Prerequisites
Working on your own computer:
!
You'll need to install the Java JDK 6
!
You need Eclipse 3.6. Other versions of Eclipse are also supported. Check
http://developer.android.com/sdk/requirements.html
for details.
!
Android SDK - http://developer.android.com/sdk/installing.html

!
Android ADT (Android Development Tools) plugin for Eclipse -
http://developer.android.com/sdk/eclipse-adt.html#installing

!
You need to have completed Tutorial 1


Working on a lab computer:
!
Eclipse and the Android SDK and ADT plugins are already installed.
!
You need to have completed Tutorial 1


Step 1: Download the Cloud Tunes Project and Mobile SDK
The code for this tutorial is available as an Android project that you can download and install in Eclipse. The project
has most of the Android specific plumbing (such as setting up the various Activities, permissions etc.) baked in so
that you can just focus on the pieces of the application that interact with Force.com.

1.
Download the Android project file from
http://media.developerforce.com/workbooks/mobile/CloudTunes.zip

2.
Go to developer.force.com/workbooks
and navigate to the Mobile Workbook
3.
Download and unzip the Mobile SDK (for Android)
Step 2: Create an Android Project in Eclipse
The next step is to import the Cloud Tunes project into Eclipse so that you can peruse the code and start making
changes to it.
1.
Launch Eclipse and make sure the ‘Java' (Default) Perspective is selected (you can change the Perspective
from the top right-hand corner of the Eclipse window). If this is your first time launching Eclipse, you will
see the default ‘Welcome’ perspective. Click on the ‘Workbench’ link on the right of the screen to go into
the Java Perspective.
2.
Configure the Android SDK in Eclipse. You can do so by clicking Window->Preferences->Android
(Eclipse->Preferences->Android on a Mac) and updating the ‘SDK location’ to the root directory where
you downloaded the Android SDK (see Prerequisites section).
3.
If you're on a labs machine that already has some Eclipse projects imported - then first delete them. Right
click on each Project in the Package Explorer (left hand pane), select Delete, check the "Delete the project
contents on disk", and click OK.
4.
Go to File ->Import->General->Existing Projects into Workspace
5.
Select Next and browse to the directory where you unzipped the Cloud Tunes project in Step 1. Click
Finish.
16

Step 3: Import the
Mobile SDK library

After importing the Cloud Tunes project in the step above, you will notice several errors in Eclipse (look at the
‘Problems’ tab at the bottom). This is because the project references the Mobile SDK, and you haven’t linked the
two yet. Do that next:
1.
Go to File ->Import->General->Existing Projects into Workspace
2.
Select Next and browse to the ‘SalesforceSDK’ sub-directory under the directory where you unzipped the
Mobile SDK in Step 1. Click OK, then click Finish.
3.
Select the ‘CloudTunes’ project in the Package Explorer (left panel in Eclipse), right click and select
‘Properties’. Select ‘Android’ in the pop-up window and click on the ‘Add’ button in the Library section.
Select ‘SalesforceSDK’ in the next pop-up and hit ‘Ok’. Hit ‘Ok’ again.
17


4.
Select Project->Clean->Clean All Projects in Eclipse to resolve any remaining errors.

In this case, we’ve chosen to download the code for the Mobile SDK (which is open source) as an Android library
and then link the library to our Cloud Tunes Android project in Eclipse. The Mobile SDK is also available in
executable format as a JAR file and you can instead chose to simply import the JAR file into your Android project if
you’re not interested in the source code for the SDK.
Step 4: Add OAuth Authentication Logic
In this step, we’ll add code to the application that allows the user to login to their Force.com environment when the
application first boots up. The Mobile SDK provides a custom OAuthActivty class that handles the entire OAuth
dance with Force.com, and makes it very simple to add authentication to your mobile application.
1.
Select the CloudTunes project in Package Explorer and open the res/values/strings.xml file in
Eclipse. Enter the respective values for the oauth_consumer_key and oauth_callback_url
from Tutorial 1
Step 4. Save the updated strings.xml file. Adding values in the strings.xml is one
way to manage application ‘properties’ in Android and it is a general best practice to externalize
configuration parameters like OAuth consumer keys this way. We will reference these values later in the
code for the application.
2.
Open the src/com.salesforce.com.androidsdk.sample/AlbumListActivity.java
class in Eclipse and uncomment the following lines of code in the onCreate() method. As a shortcut,
you can also search for the ‘Uncomment this block’ string to find this and other sections of the code that
need to be uncommented.
SharedPreferences prefs = getSharedPreferences(
SharedPreferenceConstants.SHARED_PREFS_SFDC,
MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(SharedPreferenceConstants.PREF_SFDC_OAUTH_CLIENT_ID,
getResources().getString(R.string.oauth_consumer_key));
editor.putString(SharedPreferenceConstants.PREF_SFDC_OAUTH_CALLBACK_URL,
getResources().getString(R.string.oauth_callback_url));
editor.commit();

18

The code above shows how you pass the OAuth parameter values to the Mobile SDK. Notice also how we’re getting
the values for the OAuth Consumer Key and Callback URL from the properties file that we had updated earlier (that
is what the getResources().getString() statement does).

The two configuration values that you’re required to pass to the Mobile SDK via SharedPreferences are the
OAuth Consumer Key and the Callback URL. Optionally, you can also choose to override the default behaviour of
the SDK and have it point to a Sandbox environment by setting the
SharedPreferenceConstants.PREF_SFDC_USE_SANDBOX value to true.

Now, uncomment the next block of code in the AlbumListActivity.java class.

@Override
public void onResume(){
super.onResume();

if (token == null && !cancelled){

Intent i = new Intent(this, OAuthActivity.class);
startActivityForResult(i,
OAuthActivity.REQUEST_AUTHENTICATE);
} else if (!dataFetched){

getAlbums();
}
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == OAuthActivity.REQUEST_AUTHENTICATE){
if (resultCode == RESULT_OK && data != null){
token =
data.getParcelableExtra(OAuthToken.KEY_TOKEN);
cancelled = false;

} else if (resultCode == RESULT_CANCELED){
cancelled = true;
Toast.makeText(this, "Login cancelled",
Toast.LENGTH_SHORT);

} else if (resultCode == OAuthActivity.RESULT_FAIL){
cancelled = false;
Toast.makeText(this, "OAuth Login failed",
Toast.LENGTH_SHORT);

}
}
}

This code shows how an Android application invokes the OAuthActivity class of the Mobile SDK to perform
the necessary OAuth login and authentication. The onResume() method is part of the standard life-cycle
of an
Android Activity (every screen that a user sees on an Android device is termed an ‘Activity’). Android invokes this
method every time that an Activity is displayed on the mobile device (e.g. when the Activity is first invoked or when
a user navigates back to it via the ‘Back’ key).

In this method, we first check to see if the user has already authenticated with Force.com (by checking the value of
the token variable). If the user has not yet authenticated with (i.e. the token variable is null), we simply kick
off the standard OAuthActivity that comes bundled with the Mobile SDK. This is exactly what the
startActivityForResult() method does. The Mobile SDK takes care of the rest and displays the login
page, intercepts the OAuth callback and in general implements the entire OAuth dance on Android.

19


After the OAuth dance is over, the SDK returns control back to the parent application via a call to the
onActivityResult method. The code above shows how you can extract the OAuthToken (token variable) if
the authentication succeeds. The application can also take appropriate action if the OAuth authentication fails or if
the user decides to hit the ‘Cancel’ button.
Step 5: Query and List Albums
In this step, we’ll add code that uses the Mobile SDK to query the database for Album records and display the result
in a simple list on the Android device. The Mobile SDK uses the REST API under the covers to perform all CRUD
operations. The toolkit, however, completely shields the developer from such low-level connectivity details and
instead exposes a simple interface to query, update, delete and add data.

In the src/AlbumListActivity.java class, uncomment the following block of code and save your changes.

private void getAlbums(){

dataFetched = true;
SFRestAPI api = SFRestAPI.getApi();

String soql = "select id, name, description__c, Price__c,
Released_On__c from Album__c";
try {
api.send(getApplicationContext(),
token,
api.requestForQuery(soql),
listener,
null);
} catch (SFRestException e) {
e.printStackTrace();
displayError(e.error_description);
}
}


private SFRestAPIListener listener = new SFRestAPIListener(){

public void didLoadResponse(SFRestResponse response) {

if (response == null)
return;
if (response.jsonObject == null)
return;
try
{
JSONArray records =
response.jsonObject.getJSONArray("records");

if (records.length() == 0)
return;

albums = new String[records.length()];
albumIds = new String[records.length()];

for (int i = 0; i < records.length(); i++){
JSONObject album = (JSONObject)records.get(i);
albums[i] = album.getString("Name");
albumIds[i] = album.getString("Id");
}



20

ArrayAdapter<String> ad = new ArrayAdapter<String>(
AlbumListActivity.this,
R.layout.list_item,
albums);
setListAdapter(ad);
} catch (JSONException e) {
e.printStackTrace();
}
}

public void didFailLoadWithError(SFRestResponse response) {
try{
displayError(response.getRestErrorCode());
}
catch(JSONException e){}
}

public void requestDidCancelLoad(SFRestResponse response) {
try{
displayError(response.getRestErrorCode());
}
catch(JSONException e){}
}

public void requestDidTimeout(SFRestResponse response) {
try{
displayError(response.getRestErrorCode());
}
catch(JSONException e){}
}

};

Let's walk through the code. The getAlbums() method is invoked from the onResume() method that we
uncommented earlier after the user has successfully logged in using OAuth. This method encapsulates the simple
code necessary to perform SOQL queries using the Mobile SDK. The SFRestAPI is the singleton class that wraps
all the resources supported by the REST API (query, create, update and so on) and exposes them as simple methods
that you can invoke in your Android application. This is the only class that you should ever have to use if you want
to query or manipulate data (or metadata) from Force.com.

The SFRestAPI class has methods that create the appropriate HTTP request for the respective REST API
resources - e.g. requestForQuery, requestForDescribeGlobal,
requestForRetrieveWithObjectType, requestForUpdateWithObjectType and so on. Combine
the send() method and a requestForXXX method, and you can access any of the resources supported by the
REST API. This is what the getAlbums() method does to query Album records.

One of the parameters passed to the send() method is a SFRestAPIListener instance. This parameter
illustrates the asynchronous nature of the SFRestAPI class. You need to pass in a listener to each send invocation.
The SDK then performs the necessary REST API calls asynchronously, and calls methods on the listener when the
call completes (or fails).

The second half of the code above shows how you can implement such a listener. The didLoadResponse()
method of the SFRestAPIListener interface is invoked by the SDK once an API call completes successfully.
The didLoadResponse() method extracts the JSON response and displays the Album records in a simple list.

21

Step 6: Query and List Tracks
Once the user is presented with a list of Albums, they can click on any Album record. This action will then display a
new screen (Activity) with the list of Tracks of the selected Album record. In this step, we’ll add code to the
Activity that queries for the Track data and displays it on the Android device.

Open the src/TrackListActivity.java class in Eclipse, uncomment onResume(), getTracks() and
the listener implementation, and save your changes.

The basic structure of the code follows that of the previous step. This is to be expected since this Activity performs a
very similar action to the one before - i.e. querying data using the Mobile SDK and displaying the result in a simple
list. The only real difference is the SOQL query that is executed and the related parsing of the response data. You
can see the SOQL and the use of the Mobile SDK in the getTracks() method. As before, the send() method
of the SFRestAPI class is passed a SFRestAPIListener listener which gets invoked by the SDK once the
query call completes. The didLoadResponse() method of the listener then processes the JSON response and
displays the list of Tracks.
Step 7: Putting It All Together
It's now time to run the application. First though, there's a few things to configure:
Working on your own computer:
In order to run the application in the Emulator you need to setup at least one Android Virtual Device
(AVD) that targets Platform 2.2 or above (we recommend 2.2). To learn how to setup an AVD in Eclipse,
follow the instructions at http://developer.android.com/guide/developing/devices/managing-avds.html
.
Working on a lab computer:
The Android Virtual Device (AVD) is already configured.

With all the plumbing now done, it’s time to see the results in action. To run the application, first make sure that all
your changes have been saved, highlight the CloudTunes project in Package Explorer and finally choose Run->Run
and select “Android Application”.

This will run the application in a local Android Emulator on your machine. Note that the Android Emulator may be
slow to boot up and can take several minutes for the Emulator to start. Upon startup, you will initially be presented
with the Android home screen. Swipe the lock icon to the right to display the application.

If you’d rather run and debug the application in an actual Android device, you can follow these instructions -
http://developer.android.com/guide/developing/device.html
.

When the application first starts up, it will display a login page for you to login to your Force.com application
(shown in the figure on the left).

After logging in you’ll be asked to approve the Cloud Tunes application (shown in the figure on the right). This is
all part of the OAuth dance. If you’re testing the application on an Android mobile device (and not the Emulator)
you will be required to go through an extra step of identify verification the first time you login to Force.com. In this
step you will be emailed a verification code that you will then need to enter in the mobile device to confirm your
identity.

22



After approving the application, you’ll be presented with the list of Album records that are stored in your database -
this is the AlbumListActivity.java class that you worked on in Steps 4 and 5. This is shown in the figure
on the left, below.



23


Click on any Album record, and you’ll be presented with the list of Tracks - this is the
TrackListActivity.java class that you worked on in Step 6. This is shown in the figure on the right, above.
Summary
In this tutorial you learned how to create, configure and run an Android application that retrieved data from
Force.com. The Mobile SDK provided wrappers that simplify the implementation of OAuth and the interactions
with the REST API.


24

Tutorial 4: Creating an HTML5 Application
HTML5 lets you create lightweight interfaces for users without the need to install any native software on their
mobile devices. In this tutorial, you will create a mobile application that fetches data from Force.com, while using
the REST API for access and OAuth for authentication. The tutorial will also utilize the jQuery Mobile library for
the user interface and the JavaScript REST library to handle the REST API and OAuth access.
Prerequisites
You need to complete Tutorial 1
.

In this tutorial you will create an HTML5 application - and the associated JavaScript and HTML has to be hosted on
a web server somewhere. You'll also need a proxy that will allow the application to access data across domains, as
JavaScript’s security protocols block callouts to different domains. In this tutorial, you'll use a proxy written in PHP
- so all in all you'll need a web server and PHP interpreter.

Working on a lab computer:
!
The lab computer already has PHP and an Apache web server installed. You can find your local web
server directory in the ~/Sites directory.

Working on your own computer:
!
You’ll need to install Apache and PHP on your machine. Most Unix distributions, including OS X, should
have these installed. For Windows, try WampServer http://www.wampserver.com/


In either configuration, you will need to be able to access your localhost at a particular port. The rest of this tutorial
assumes you can reach your web server on port 80 at http://localhost
. Change the URL depending on your web
server and port installation.

Your Apache web server will have a document folder where you store the files. We're going to assume your web
server document folder is in the ~/Sites directory - the standard directory on the labs machines. Change this
according to your local configuration.

This workbook also assumes you'll be doing the workbook as a local user, and not have access to the root document
folder - so all in all our complete local URL will be http://localhost/~admin/
. If you're doing this on your own
machine, the URL may be something like http://localhost/~yourloginname/
- make sure you use the appropriate
URL in the callback URL below.
Step 1: Download Sample Application
The sample application contains the PHP script to handle the proxy for our web server, the libraries required to
utilize the REST API via JavaScript and the basic skeleton for our jQuery based interface.

!
Download the HTML5 sample application from
http://media.developerforce.com/workbooks/mobile/HTML5.zip

!
Unzip the file. Take all the files from the HTML5 directory created by the unzip process, and place them
into the root of your local Apache web document folder - in our case in ~/Sites. Click yes, if prompted
to overwrite any files.
!
Visit your web site. In the labs, it will be http://localhost/~admin/


Your browser will now display a simple launch page with a Login button.

25

The index.html file provides you with an HTML interface to your application and merits some explanation.
Open it up and take a look. At the top, it references the files it needs to run:
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-
1.0b1.min.css" />
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>
<script type="text/javascript" src="forcetk.js"></script>
<script type="text/javascript" src="cloudtunes.js"></script>
<script type="text/javascript" src="login.js"></script>

The application uses jQuery and jQuery Mobile to control the interface, which accounts for the majority of these
includes. The forcetk.js provides the library for interfacing with the REST API.
The HTML is divided up into divs that describe specific pages for our interface. Note that these have identifiers
that will be used later. For example, detailpage is used to identify the HTML segment that will eventually be
used to display the album data:
<div data-role="page" data-theme="b" id="detailpage">
<div data-role="header">
<a href='#mainpage' id="backAlbums" class='ui-btn-left'
data-icon='arrow-l' >Albums</a>
<h1>Album</h1>
</div>
<div data-role="content">
<h1 id="AlbumName"></h1>
<table>
<tr><td>Price:</td><td id="AlbumPrice"></td></tr>
</table>
<input type="hidden" id="AlbumId" />
<ol id="tracklist" data-inset="true" data-role="listview"
data-theme="c" data-dividertheme="c">
</ol>
</div>
</div>
jQuery Mobile is capable of splitting these divs up and treating them as separate portions of an interface. Consider
the case when our JavaScript later calls a function like this:
$j.mobile.changePage('#detailpage', "slide", false, true);
Here, jQuery Mobile will change the page to the div with an id of detailpage using a slide animation.
Step 2: Setup OAuth
Follow Tutorial 1
Step 4 to create a second Remote Access configuration. Call the new configuration "Test Client
HTML5", and provide a callback URL of http://localhost/~admin/oauthcallback.html
.
Unlike the case of the mobile tutorials, this URL will be invoked on a successful completion of the OAuth dance. If
your web server has a different URL or port, please be sure to modify the URL accordingly.
Open login.js in an editor. At the top of the file, modify the code at the top that reads:
26

// OAuth Configuration
var loginUrl = 'https://login.salesforce.com/';
var clientId = 'CONSUMER_KEY';
var redirectUri = 'http://localhost/~admin/oauthcallback.html';
var proxyUrl = 'http://localhost/~admin/proxy.php?mode=native';
Add your consumer key, from your Remote Access, to the clientId variable. You may have to change your
redirect and proxy URLs, depending on where you post your files. In particular, you may need to replace ~admin
to match your local web server configuration. Now save the file.
Note the proxyUrl variable, which is how the JavaScript REST toolkit understands where the PHP proxy resides.
When we start making REST callouts, this proxy will be needed so that JavaScript can get data remotely from
another domain.
Now refresh the web page for the application so that the update files are loaded: http://localhost/~admin/
. Upon
clicking the “Login” button, you will get a popup window that asks for the user login and granting of application
permissions via OAuth:

Click Allow. You will now have authenticated against the database. Your application doesn't do much more yet -
you'll see a "loading" message. We'll get to that next. What has happened though, is that the OAuth dance has
come to an end, and your application has an access token and instance URL.
Step 3: Retrieving and Displaying Albums
Now that we’ve configured the necessary information to access OAuth, you can add the JavaScript needed to access
data securely.
Open up cloudtunes.js and remove the comments around the getAlbums() and showAlbums() methods.
Here's the getAlbums() method:
function getAlbums(callback) {
$j('#albumlist').empty();
client.query("SELECT Id, Name, Price__c FROM Album__c ORDER BY Name LIMIT 20",
function(response) { showAlbums(response.records,callback) });

27

}

This is the function called after logging in. Function calls such as $j('#albumlist').empty(); are an
indication of jQuery at work. In this case, jQuery retrieves the HTML element identified by albumlist, and
clears out the HTML - readying it for results.

The client() call is an invocation on the JavaScript REST toolkit, in this case used to make a SOQL call to
retrieve data. This is the code that uses the proxy.php file to return a value from the REST endpoints.

Finally, the method ensures that a callback function is invoked to show the albums once the data is returned from the
SOQL query - passing in the array of results and also any code which should be triggered after the records are
processed. The showAlbums() method, which should now be uncommented, takes these records and displays
them.

function showAlbums(records, callback) {
currentAlbums.length = 0;
for(var i = 0; i < records.length; i++) {
currentAlbums[records[i].Id] = records[i];
}
var x = 0;
$j.each(records,
function() {
$j('<li></li>')
.attr('id',this.Id)
.hide()
.append('<h2>' + this.Name + '</h2>')
.click(function(e) {
e.preventDefault();
$j.mobile.pageLoading();
$j('#AlbumName').html(currentAlbums[this.id].Name);
$j('#AlbumPrice').html('$'+currentAlbums[this.id].Price__c);
if($j('#AlbumPrice').html().indexOf(".") > 0 &&
$j('#AlbumPrice').html().split(".")[1].length == 1) {
$j('#AlbumPrice').html($j('#AlbumPrice').html()+"0"); //add
trailing zero
}
$j('#AlbumId').val(currentAlbums[this.id].Id);
$j.mobile.pageLoading(true);
$j.mobile.changePage('#detailpage', "slide", false, true);
getTracks(currentAlbums[this.id].Id);
})
.appendTo('#albumlist')
.show();
x++;
});

$j('#albumlist').listview('refresh');
if(callback != null) { callback(); }
}

This function gets the records from the SOQL query, loops through them and creates a new list of list item HTML
elements to display within the albumlist div on index.html. It also dynamically attaches a new event to each
list item so that when the user clicks on the list item, they can browse down to a list of tracks associated with the
album.

We’ll add the ability to access the tracks in the next step. For now, you should be able to test the application by
clearing your browser cache (for Safari choose Empty Cache from the Application menu, or for Firefox hold
28

SHIFT, and click reload), and reloading the main page. Go through the OAuth process to see a list of albums
(based on your test data) which looks like this:

Step 4: Retrieving and Displaying Tracks
Now go back to the cloudtunes.js file.
1.
Uncomment out the lines for the body of getTracks() and the showTracks() method.
Functionally, this code is very similar to the getAlbums() and showAlbums() code. Here's the code for
getTracks():
function getTracks(albumid, callback) {
$j('#tracklist').empty();
client.query("SELECT Id, Name, Price__c, Album__c, Album__r.Name FROM
Track__c WHERE Album__c = '"+albumid+"'
ORDER BY CREATEDDATE LIMIT 200",
function(response) { showTracks(response.records,callback) } );
return true;
}
The only significant difference to the code that handled albums, is that a different query is used, and of course a
different div is updated with the results.
2.
Save the file, clear your cache, and reload your web site from the root URL: http://localhost/~admin/
.
Finally, login again.
Now anytime the album name is clicked, a new set of track data will be retrieved and the itemlist will be rewritten.
Clicking on the track name will rewrite the HTML of the elements displaying the track information and use jQuery
mobile to move to that page. A real application may of course cache this information as well.
29


Step 5: Putting It All Together
Let’s take a step back to see what we’ve put together here and how it works. The main index.html provides all
the interface for the application, by dividing the HTML into specific div elements for jQuery Mobile to use to
generate a mobile interface.
The login.js file holds the configuration and logic required to perform the OAuth authentication loop. Once the
loop is completed, it can hand the security token and endpoint URL information to the forcetk.js library.
The JavaScript library, forcetk.js, provides access to the REST API on Force.com. Because JavaScript has a
security restriction that keeps it from calling external endpoints directly, the library can only retrieve data from the
same domain the HTML page is being delivered from - localhost in our case. So in order to access the REST API,
the JavaScript calls the PHP proxy file on localhost, which in turns makes the call to the REST API and returns the
data back to the JavaScript client. So the PHP proxy is an intermediary providing access to the REST API simply
because of the JavaScript security model.
In forcetk.js, calls to the REST API are made by using JavaScript HTTP callouts, passing in the OAuth token
in the HTTP header. For example, here's an excerpt:
forcetk.Client.prototype.query = function(soql, callback, error) {
this.ajax('/' + this.apiVersion + '/query?q=' + escape(soql)
, callback, error);
}
This, in turn, makes use of a utility method that does the actual callout - constructing the familiar REST API URL to
the resource, and adding the session token to the header:
forcetk.Client.prototype.ajax = function(path, callback, error, method, payload,
retry) {
var that = this;
var url = this.instanceUrl + '/services/data' + path;
$j.ajax({
type: method || "GET",
data: payload,
success: callback,
/* … */

30

},
dataType: "json",
beforeSend: function(xhr) {
/* … */
xhr.setRequestHeader(that.authzHeader, "OAuth " +
that.sessionId);
}
});
}

In cloudtunes.js we have the specific functionality for getting data to the user interface. We use the client
created in forcetk.js to access the endpoints of the REST API, and manipulate the results. For instance, in
getAlbums(), we can use SOQL to query against the REST API and send the data back to jQuery. jQuery then
takes the data and generates the list of results, using jQuery Mobile to create a mobile friendly layout for the
application.
Summary
In this tutorial you created an HTML5 application that retrieves and displays data from your database. The
application uses jQuery and jQuery Mobile to perform the display magic, and a PHP proxy in order to handle the
single-origin JavaScript requirement.





31

Tutorial 5: Creating an iOS Container Application
In this tutorial you create a hybrid iOS application using the HTML5 code from Tutorial 4
as a starting point.
Hybrid applications can run natively on a device�however the interface and business logic can be built with HTML,
CSS and JavaScript�reducing the amount of native code needed to build the application. This tutorial uses a
developer preview of the iOS container, part of the Mobile SDK, to construct the hybrid application. It currently
also uses a container from PhoneGap.
Prerequisites
Working on a lab computer:
!
You need to complete Tutorial 4
.

Working on your own computer:
!
You need to complete Tutorial 4
.
!
You need Xcode 4.0.2 installed.
!
You need PhoneGap installed ( http://www.phonegap.com/
)
Step 1: Download the Container Sample Application
This tutorial will use a sample application as a starting point. This is an Xcode project, which provides the base for
using OAuth for login as well as integrating the HTML5 code into the native application:
1.
Download the Container sample application from
http://media.developerforce.com/workbooks/mobile/CloudTunesContainer.zip

2.
Unzip the file.
3.
Double click the CloudtunesContainer.xcodeproj file to open the project in Xcode.
Step 2: Add the HTML5 Application to the Container
Copy the files from Tutorial 4, which should all be in your web server document root (which is ~/Sites in the lab
machines) and paste them into the www folder of the sample application:
1.
Open the files from Tutorial 4
in Finder (on a labs machine or using the default OS X setting, they will be
in ~/Sites). Select all of them, right click and copy them.
2.
In the unzipped Container sample application folder, open the www folder.
3.
Paste the files into the www folder.
4.
Xcode will automatically detect that the files have been added, and the Project Navigator will display them:


The proxy.php file isn't needed, but it won't do any harm if you copy it over.
Step 3: Add your OAuth Consumer Key

32

Within Xcode, go to Project Navigator and open the folder SFPGContainer. Now open Classes. Click on
AppDelegate.m.



Find the following line of code:
static NSString *const remoteAccessConsumerKey = @"CONSUMER_KEY";

Change CONSUMER_KEY to the consumer key from Tutorial 4
. Be careful not to replace the @ or the rest of the
line. (You can also find the consumer key in the login.js file). Save the modified AppDelegate.m file.
Step 4: Update login.js
In the previous tutorial, the login.js file handled the OAuth flow (using JavaScript and the proxy). In hybrid
applications, the container has the logic to handle the OAuth, so we're just going to plug into that. As a result, you
won't need the login.js file from the HTML5 project. Instead, replace it with the login_container.js
file.

To replace the login code, go the www folder in Finder. Delete login.js, and rename login_container.js
to login.js. Take a look at the code:

function onBodyLoad() {
document.addEventListener("salesforce_oauth_login",
onSalesforceOAuthLogin,false);
document.addEventListener("deviceready", onDeviceReady,false);
}

function onDeviceReady() {
try {
$j.mobile.changePage('#mainpage', "slide", false, true);
$j.mobile.pageLoading();
getAlbums(function() {
$j.mobile.pageLoading(true);
});
} catch(e) {
alert(e);
}
}

function onSalesforceOAuthLogin(event) {
client = new forcetk.Client(event.data.clientId,
event.data.loginUrl);
client.setSessionToken(event.data.accessToken,
event.data.apiVersion,
event.data.instanceUrl);
client.setRefreshToken(event.data.refreshToken);
}
33

Since the native code in the Container project sets up the main OAuth authentication flow, this JavaScript file is now
only responsible for setting up what happens when events are complete, which it does when the document body is
first loaded by calling onBodyLoad().
The onSalesforceOAuthLogin() function will be called when the OAuth dance is complete and the security
tokens can be stored, and onDeviceReady() is called when the interface returns to our application after OAuth
is complete. This method sets up a client instance, passing in the access token and instance URL returned from
the login. It's this instance that can be used from within your JavaScript to interact with the REST API.
Step 5: Update index.html
While the HTML interface and the main JavaScript code does not need to change from the HTML5 tutorial, you will
need to update some of the references in index.html, specifically adding a reference to the PhoneGap JavaScript
library used to communicate between the HTML5 application and the native code.
Open the index.html file and remove the comments around the last JavaScript script import:
<script type="text/javascript" src="phonegap-1.0.0.js"></script>
This library provides the bridge between JavaScript and the native container. This is used to initiate the OAuth
flow, and can also by used by similarly designed apps to access native device functionality such as the camera.
Access to the REST API, and handling the mobile interface, is done with the exact same code as the HTML5 project
from Tutorial 4
.
Step 6: Compile and test.
You can now compiler and run the application.
!
Click Command-R
After compiling, the simulator will start up your native application, and you'll see the embedded HTML5 application
interface from Tutorial 4
as well.

To deploy to a device, follow the same routine documented at the end of Step 2 in Tutorial 2
.

34

Step 7: Putting It All Together
Most of this tutorial was simply configuration - you've already written the application - the HTML5 application.
This illustrates the beauty of this technique - it's simply embedding the HTML5 files within a native container. The
only significant change was to login.js, which hooks into the container's OAuth handler.

The container starts and handles the OAuth process for you, passing control to the
onSalesforceOAuthLogin() method once that's done. The container then loads index.html, and when
ready triggers the onDeviceReady() method. In our case, that method updates the album data on
index.html.

At this point, the application operates as it did in Tutorial 4
, but does so from within a browser component within a
native application as opposed to a mobile browser.
Summary
Congrats! In this tutorial you created a hybrid application by utilizing a container that lets you embed HTML5
applications. The only changes to the HTML5 application were in the configuration of the JavaScript/Container
bridge, and intercepting the container's callbacks for OAuth. You can now change the application to make
additional REST API calls, modify the user interface, and make use of device-native capabilities, all from within the
realm of HTML5, CSS and JavaScript.

35

Next Steps
If you've completed this workbook, then you should have a good idea of how to build mobile applications - both
native, HTML5, and hybrid - that access Force.com or Database.com using OAuth 2.0 and the REST APIs.

To continue exploring, visit:
!
http://developer.force.com/mobile
to learn more about the Mobile SDK. You'll also be able to access the
latest version of the Mobile SDK here.
!
http://developer.force.com/
to learn more about Developer Force
!
http://www.database.com/
to learn more about Database.com