Getting Started with the Mobile SDK for Android

Introduction

The Mobile SDK is targeted at developers looking to create mobile applications that interact with Salesforce.com, Force.com, or Database.com. Currently, the SDK supports building two types of mobile applications—native and hybrid.

  • Native applications are specific to a given mobile platform (e.g., iOS, Android, Blackberry) using the development tools and language that the respective platform supports (e.g., Xcode and Objective-C with iOS, Eclipse and Java with Android). The Mobile SDK provides libraries for Android and iOS developers looking to develop natively on these two platforms.
  • Hybrid applications, on the other hand, primarily use standard web technologies—typically HTML5, JavaScript and CSS. This write-once-run-anywhere approach to mobile development creates cross-platform mobile applications that work on multiple devices and platforms. While developers can create sophisticated apps with HTML5 and JavaScript alone, some vital limitations remain at the time of this writing, specifically session management, access to native device functionality like the camera, calendar and address book, etc. The hybrid version of the Mobile SDK (based on the industry leading PhoneGap implementation) makes it possible to embed HTML5 apps inside a thin native container, producing a hybrid application.

This article covers the use of the Mobile SDK to develop native Android applications. It does not demonstrate how to create hybrid mobile apps. To understand how you can use the SDK to develop a native iOS application, please refer to this article.

Prerequisites

The Mobile SDK only supports Android 2.2 and above. The Mobile SDK requires that you set up the target computer with the basic Android development environment. Specifically, the SDK requires:

This article also assumes that you have basic knowledge of developing native Android applications (e.g., concepts like Activity, Intent). You can refer to the Android Developer Guide for further details.

Installation

The Mobile SDK is an open source library—the entire codebase for the SDK is available on GitHub. You can download the Android half of the SDK from this GitHub repository. You can either clone the repository into your local development environment by running
git clone https://github.com/forcedotcom/SalesforceMobileSDK-Android.git
from the command line, or if you're not familiar with Git and GitHub, you can simply download the SDK as a zip or tar file and extract the contents.

After downloading the SalesforceMobileSDK-Android project from Github, run the install script from the command line:

cd SalesforceMobileSDK-Android 
$./install.sh

Windows users can run cscript install.vbs from the command line instead.

Note: The GitHub project for the Android SDK contains both the native and hybrid bits. Because this article only focuses on native Android development, you will only use the native and dist sub-directories in the project.

Once you have downloaded and installed the Android SDK on your local machine, you have two options for using the SDK in your own Android project/application:

  • You can choose to import the entire code-base for the SDK into Eclipse and then link your Android project to it.
  1. Import the SDK project into Eclipse by going to File → Import → General → Existing Projects into Workspace.
  2. Point to the /SalesforceMobileSDK-Android/native/SalesforceSDK directory.
  3. Link the SDK to your own Android project.
  4. In Eclipse, select your Android project and then go to Project → Properties → Android, and click Add... in the Library section to add a reference to the SalesforceSDK library project that you imported earlier.
  • The previous option is ideal if you wish to peruse the actual SDK code as you're developing your Android application. If you'd rather just use the SDK binaries, you can simply copy the latest SDK jar file (currently 'SalesforceSDK-1.0.1.jar') from the SalesforceMobileSDK-Android/dist directory into the 'libs' folder of your project.

Getting Started

There are a couple of different ways to start a new Android project that uses the Mobile SDK. You could choose to start with a brand new Android project, include the SDK in it (using either of the two methods that the previous section describes) and then add the necessary scaffolding to use the SDK.

A quicker and easier option is to import a simple template project that the Mobile SDK includes and then add your application specific implementation. With this approach, you don't have to worry about how to include the SDK in your project or putting together the scaffolding from scratch—the template project takes care of all that. You can simply import that project into Eclipse, make some minor updates, and then start adding your application logic.

To import the template project, go to File → Import → General → Existing Projects into Workspace, and then point to the /SalesforceMobileSDK-Android/native/TemplateApp directory. This should import the project into Eclipse. Next, make the following updates to the template project to customize it to your specific application requirements.

  1. Open the AndroidManifest.xml file by right-clicking on it and selecting Open With → Android Manifest Editor.
  2. At the top of the first tab, you’ll see the Package field. This contains a unique identifier to use out on the Android Market to differentiate your app’s code and resources. To make this identifier unique to your application, change the value to something unique (e.g com.mycompany.myappp), then save the file. In the following dialog asking if you want to change launch configurations, click Yes.
  3. Next, in order to fix all the new build errors that you now see in Eclipse, expand the src/ folder in the project. Right click the package name (currently com.salesforce.samples.templateapp) and select Refactor → Rename. You will be prompted to give a new name. Change this value to something unique like com.mycompany.myappp, and click OK.
  4. You will be presented with a warning that this package already exists in the gen/ folder. Click Continue. Your build errors should disappear.
  5. Finally, expand the res/values/ folder, and open rest.xml. Change com.salesforce.samples.templateapp.login to your unique package name (e.g. com.mycompany.myappp).
  6. The Mobile SDK uses OAuth 2.0 for authenticating with Salesforce.com. Therefore, you need to create a new Remote Access Application in Salesforce.com (Setup → Develop → Remote Access). Next. in the same rest.xml file, update the value of oauth_callback_url to the callback URL that you registered in the Salesforce.com Remote Access application (you can use something like 'sfdc://success'). Next, update the value of oauth_client_id to the Consumer Key that was assigned to your Remote Access application in Salesforce.com.
  7. Next, If you click over to the Application tab of the AndroidManifest.xml document, you should see the Label field set to @string/app_name. This is how your app will be labelled on the device. In order to update your application name, expand the res/values folder of the project. Right-click on strings.xml and select Open With → Android Resource Editor. Click on the app_name row of the left pane. In the right-hand pane, change the value from TemplateAppt to your unique application name, and save the file.

That's it! You are now ready to start adding your application logic. The template project assumes MainActivity.java to be the main Activity of the application (i.e., it is the first screen that users see once they login to Salesforce.com) and so you can start by adding your application specific code to that class.

Components of the Template project

Let's briefly look at some of the scaffolding that the template project includes and that you'll use with the SDK. If you choose to create a new Android project from scratch (instead of modifying the template project), you'll need to include these components in your project.

SalesforceRImpl.java

Each Android project that uses the Mobile SDK must provide an implementation of the SalesforceR.java interface (which is what SalesforceRImpl.java does). This is a way for your application to give the Mobile SDK references to some of the resources that the SDK requires at run-time (e.g., the layout to use for displaying the main Login Activity). In most cases, you don't have to modify the default SalesforceRImpl.java class that the template project includes. You should only ever have to modify the SalesforceRImpl.java class if you need to override some default behavior of the SDK (e.g., to customize the error message that displays when a Salesforce authentication fails).

TemplateApp.java

Every Android project that uses the Mobile SDK also must provide an Application class that extends the abstract com.salesforce.androidsdk.app.ForceApp class — in the template project, you do this with the TemplateApp.java class. The most important method in TemplateApp.java, and one that you may have to modify, is the getMainActivityClass() method. You should return the Activity class that you'd like to display when the user first logs into your Android application (the template project defaults to MainActivity.java).

AndroidManifest.xml

One of the most important files in an Android project is the Manifest file. The Manifest file specifies things such as the user permissions, Activities, and Services that your application uses. The Mobile SDK requires certain updates to the Manifest file (e.g., specific user permissions and Services). The Manifest file for the template project includes all these updates, so if you choose to simply import the template project and modify it as in Getting Started, you should not have to make any additional updates.

Authentication

The Android Mobile SDK includes two principle components—an OAuth 2.0 implementation for authenticating and authorizing with Salesforce.com, and simple wrappers for the Force.com REST API that allow easy CRUD access to data in Salesforce.com.

The following code from the onResume method of the MainActivity.java class illustrates how to authenticate the user using the SDK.

	@Override 
	public void onResume() {
		super.onResume();
		
                // Hide everything until we are logged in
		findViewById(R.id.root).setVisibility(View.INVISIBLE);
				
		// Login options
		String accountType = ForceApp.APP.getAccountType();
    	        LoginOptions loginOptions = new LoginOptions(
    			null, // login host is chosen by user through the server picker 
    			ForceApp.APP.getPasscodeHash(),
    			getString(R.string.oauth_callback_url),
    			getString(R.string.oauth_client_id),
    			new String[] {"api"});
		
		// Get a rest client
		new ClientManager(this, accountType, loginOptions).getRestClient(this, 
                    new RestClientCallback() {
			@Override
			public void authenticatedRestClient(RestClient client) {
				....				
				// Show everything
				findViewById(R.id.root).setVisibility(View.VISIBLE);

				//User is authenticated, insert Application logic here
				.....
			}
		});
	}

Instead of invoking an explicit login method or Activity, you invoke authentication by instantiating a new ClientManager object (line 18) and invoking the getRestClient method. The SDK automatically detects if the user is already logged in, and if not, it initiates the OAuth authentication flow by redirecting the user to the Salesfore.com login page. One of the parameters passed to the ClientManager is LoginOptions. This is the class where you specify authentication parameters like the login server (Production vs Sandbox), the OAuth callback URL and Consumer Key, etc. Because the SDK implements the entire OAuth flow internally, all that your application must do is register a RestClientCallback object to receive an asynchronous callback once the user has successfully authenticated with Salesforce.com.

This asynchronous nature of receiving a callback from the SDK is essential if your app requests authentication from the main UI thread, as in the example above. Considering that Android does not allow blocking operations like HTTP requests from the main UI thread to ensure application responsiveness, your app must call the asynchronous getRestClient method when using the SDK from the context of a UI Activity. If your app needs to access RestClient from a non-UI context (e.g., from a ContentProvider or BroadcastReceiver), your app can use the synchronous peekRestClient method instead.

Note that calls to the getRestClient or peekRestClient methods result in a login challenge only when the user hasn't already logged in once. The SDK keeps track of the user's login status internally and abstracts away these details from the application developer completely.

Internally, the Mobile SDK uses the Android AccountManager to store the access tokens associated with a given user's Salesforce.com login. Users can view and delete this account information by going to 'Settings → Accounts & sync' on their Android device.

Refresh Token Flow (aka Remember Me)

Though it may not be evident from the code snippet above, the Android Mobile SDK implements the OAuth 2.0 Refresh Token Flow internally. In other words, if the access token granted as part of the OAuth flow expires, the SDK automatically and seamlessly rehydrates the access token using the refresh token. Internally, the SDK encrypts and stores the access and refresh tokens related to the OAuth flow, thus maintaining maximum security. All of these implementation details are completely transparent to you, the app developer. And once a user logs into your application, they shouldn't ever have to re-authenticate with Salesforce.com when they open the application in the future.

Note that users can revoke refresh tokens from the Salesforce.com console (Setup → My Personal Information → Personal Information → Remote Access). In this case, the user would see a username/password prompt when they open the Android application.

Passcode Activity

Most applications can benefit from the SDK's Remember Me feature that the section above describes. However, letting users access your application without having to login every time has important security implications. The SDK supports an additional security layer that you can optionally add to your application to make it more secure. You can require that users enter a passcode every time that they access your application after a certain period of inactivity. You can do so by adding the following lines of code before instantiating the ClientManager object (i.e., insert this on Line 7 of the code snippet in Authentication).

ForceApp.APP.getPasscodeManager().lockIfNeeded(this, true);
		
// Do nothing - when the app gets unlocked we will be back here
if (ForceApp.APP.getPasscodeManager().isLocked()) {
	return;
}

With those additional lines of code, your users will see the following screen to setup a passcode when they first launch your application. They will also be prompted to enter the same passcode when they launch your application after a period of inactivity.

SNAG Program-0047.png

You can control the inactivity time interval for your application by returning a non-zero value in the getLockTimeoutMinutes() method of the class that extends the ForceApp base class (TemplateApp.java in the template project).

Logging Out

You can invoke the following to logout the user from your application and delete all associated access and refresh tokens from the device.

ForceApp.APP.logout(MainActivity.this);

Basic CRUD Operations

In addition to the OAuth 2.0 authentication, the Mobile SDK also provides simple REST API wrappers to query and update data in Salesforce.com. The following code snippets show how you can use the SDK to perform basic CRUD operations.

Note: The SDK ships with a sample RestExplorer application (SalesforceMobileSDK-Android\native\RestExplorer) that demonstrates the use of the SDK in making various REST API calls (query, search, update, insert etc.). You can import this application into Eclipse and look at the source code (ExplorerActivity.java) for further details.

Query

Here is a small code snippet of how you can query Account records using the SDK.

RestClient client;
...
String soql = "select id, name from Account limit 10";
RestRequest request = RestRequest.getRequestForQuery(apiVersion, soql);
sendRequest(request);
.....

public void sendRequest(RestRequest request){

	client.sendAsync(request, new AsyncRequestCallback() {

		@Override
		public void onSuccess(RestResponse response) {
			try {
				/*REST API call was successful. Add business logic. 
				For e.g. to process the query results... 
            
				if (response == null || response.asJSONObject() == null)
					return;
						
				JSONArray records = response.asJSONObject().getJSONArray("records");
	
				if (records.length() == 0)
					return;
										
				for (int i = 0; i < records.length(); i++){
						JSONObject account = (JSONObject)records.get(i);
						String acctName = account.getString("Name");
				}*/
                EventsObservable.get().notifyEvent(EventType.RenditionComplete);
			} catch (Exception e) {
				e.printStackTrace();
				displayError(e.getMessage());
			}
		}
				
		@Override
		public void onError(Exception exception) {
			displayError(exception.getMessage());
			EventsObservable.get().notifyEvent(EventType.RenditionComplete);
		}
	});
}

There is a consistent pattern for making any REST API call with the SDK.

  1. First, obtain an authenticated RestClient object from the SDK (see Authentication for details).
  2. Next, construct a RestRequest object by invoking the getRequestForXXX static method that corresponds to the REST API call that you want to invoke (e.g., getRequestForQuery to run a SOQL query, getRequestForUpsert to upsert a record). All getRequestForXXX methods require an API version parameter and may require additional parameters depending on the type of operation (e.g., the SOQL string in the case of a query).
  3. Finally, invoke the sendAsync method to initiate an asynchronous REST API request. The method requires a AsyncRequestCallback parameter which the SDK asynchronously calls once the REST API call completes. Specifically, if the REST API call is successful, the SDK passess back the response as the RestResponse parameter of the onSuccess method. Conversely, if the REST API call fails, the SDK calls the onError method.

As noted earlier, Android does not allow synchronous HTTP callouts from the main UI thread. Therefore, the use of the sendAsync method is required when making REST API calls from a UI/Activity context. RestClient also has a sendSync method, but your app can call that method from outside the main UI thread (e.g., from a ContentProvider or BroadcastReceiver).

Insert

In each of the following code snippets, the sendRequest method from the previous query example encapsulates the logic to invoke the respective REST API call.

String objectType = "Account";
Map<String, Object> fields = new Map<String, Object>();
fields.put("Name","Test Account");

try {
	RestRequest request = RestRequest.getRequestForCreate(apiVersion, 
									      objectType,
									      fields);
	sendRequest(request);
} catch (Exception e) {
	....
}

Update

String objectType = "Account";
String objectId = "001C000000oh4ga";
Map<String, Object> fields = new Map<String, Object>();
fields.put("Name","Test Account 2");

try {
	RestRequest request = RestRequest.getRequestForUpdate(apiVersion, 
									      objectType,
									      objectId,
									      fields);
	sendRequest(request);
} catch (Exception e) {
	....
}

Upsert

String objectType = "Account";
String externalIdField = "Custom_ExtId_Field__c";
String externalId = "123";
Map<String, Object> fields = new Map<String, Object>();
fields.put("Name","Test Account 2");

try {
	RestRequest request = RestRequest.getRequestForUpsert(apiVersion, objectType,
										externalIdField, externalId, fields);
	sendRequest(request);
} catch (Exception e) {
	....
}

Delete

String objectType = "Account";
String objectId = "001C000000oh4ga";

try {
	RestRequest request = RestRequest.getRequestForDelete(apiVersion, 
										objectType,
										objectId);
	sendRequest(request);
} catch (Exception e) {
	....
}

Error Handling

As explained in query, if a REST API call fails, the SDK calls the onError method of the AsyncRequestCallback callback object. It is your responsibility to implement appropriate error handling in this method (e.g., by displaying a message to the user).

In the context of error handling, it is important to understand exactly what the SDK considers to be an error. The SDK treats a network level I/O exception (e.g., an HTTP timeout when trying to connect to the Salesforce.com REST API endpoint) as an error, resulting in a call to the onError method. With all other REST API exceptions (e.g., when the app passes an invalid SOQL query to the query call), the SDK calls the onSuccess method. Therefore, it is a good practice to check the RestResponse in the onSuccess method for any REST API exceptions. For example:

@Override
public void onSuccess(RestResponse response) {
		try {
			if (!response.isSuccess())
			{
				String errorCode = response.asJSONObject().getString("errorCode");
				String errorMsg = response.asJSONObject().getString("message");
				displayError(errorCode, errorMsg);
				return;                                           
			}
			//No error, continue processing response
			.....
		} catch (Exception e) {
			e.printStackTrace();
			displayError(e.getMessage());
		}
}

Advanced Topics

This article explains the basics of how to develop native Android applications using the Mobile SDK. Nonetheless, the SDK is extremely customizable and it is possible to implement more advanced features, including:

  • implementing a custom layout for the Salesforce.com login screen
  • returning a notification when a user deletes his/her Salesforce.com account from the Account Manager
  • and much more

AppExchange Mobile

Congratulations! You’ve built your mobile app and now you are ready to get it into the hands of customers. But how? You’re only two steps away from getting your app to market. First, list your app on the Android Market. This is a great way to market your app and connect with millions of customers. Second, list on AppExchange Mobile. AppExchange Mobile is Salesforce.com’s destination for mobile business apps and is part of the AppExchange—the leading business apps marketplace. As a Force.com mobile app developer, you have a unique opportunity to list on AppExchange Mobile, connecting you with a dedicated set of existing Salesforce customers who are waiting for great business apps like yours.

Learn more about listing on the AppExchange.

Mobile-appex.png

Summary

The Mobile SDK lets you develop native and hybrid iOS and Android applications that source data from Salesforce.com, Force.com, or Database.com. In this article, you learned how to use of the SDK to develop native Android applications. You can also check the Mobile SDK Workbook for additional articles and tutorials on using the Mobile SDK. The detailed Java Doc documentation for the Android Mobile SDK is also available for further reference.

Remember also that the Mobile SDK is an open source project and you can help us enhance and improve the SDK by contributing to the project. You can also use GitHub's issue tracking feature to file bug/enhancement requests. Better yet, you can fix the issue and submit a Pull Request!

About the Author

Sandeep Bhanot is a Senior Developer Evangelist at Salesforce.com. He likes long walks on the beach, a well made caipirinha and developing Android applications. You can follow his exploits on Twitter and the Developerforce blog.