Connect Salesforce with Android

In this article, we’ll explore building a simple native Android application that leverages the Chatter REST API within the Salesforce platform. For this, we’ll be using the Salesforce Mobile SDK 2.1 (acting as a wrapper around the low-level HTTP functions), allowing us to easily handle OAuth and subsequent REST API calls. The TemplateApp provided in the SDK as a base is really the cleanest starting point for you. My tutorial essentially uses the structure of a TemplateApp and builds on it by borrowing and modifying from the REST Explorer sample application; this helps keep things as simple as possible. We won’t cover every aspect of building this application, but instead cover the main points, give the reader a good starting point, and try to extend the salesforce.com documentation. This tutorial attempts to be somewhat complementary to developers who are new to the platform and using the API in ways that may be more familiar. Much of what we will cover will complement the Salesforce Mobile SDK Developer’s Guide; throughout this tutorial, I will refer to the relevant page numbers in that document rather than reproduce that information in its entirety here.

Settings

I’m using IntelliJ IDEA for this tutorial, the IDE that Android Studio is based on. If you’re already using Android Studio, your workflow won’t be noticeably different while you’re at it. Eclipse users are fine. With the IDE set up, we can install the Salesforce Mobile SDK 2.1 (see link above). Salesforce.com recommends using the node package manager for Node.js based installations. We’ll take an alternate route; instead, we’ll clone the repository from Github [page 16].

After completing the basic environment setup, go to https://developer.salesforce.com/signup and sign up for your Developer Edition (DE) account. For this example, I recommend signing up for a Developer Edition even if you already have an account. This ensures you get a clean environment with the latest features enabled. Then, navigate to http://login.salesforce.com to log in to your developer account.

After completing the registration, follow the instructions in the Mobile SDK Guide to create a connected application [page 13]. For the purposes of this tutorial, you only need to fill in the required fields.

1

The callback URL provided for OAuth is not necessarily a valid URL. It just needs to match what the application expects in this field. You can use any custom prefix, such as sfdc://.

Important note: For native applications, you must place Request at any time on your behalf (refresh_token)” in the selected OAuth scope , otherwise the server will reject you, and no one likes rejection. This is covered in the Mobile SDK Guide, and more details here: [http://github.com/forcedotcom/SalesforceMobileSDK-iOS/issues/211#issuecomment-23953366]

Once done, a page should be displayed with your consumer key and secret.

2

Now that we’ve got things done on the server side, let’s move our focus to setting up the phone application.

First, we’ll start a new project in IntelliJ. Make sure to select Application Module and not Gradle: Android Application Module as the way projects are structured doesn’t play well with the Gradle build system.

3

Name it whatever you want, and be sure to uncheck the Create “Hello World!” box. Activity , since we don’t need it. After creating the project, go to File->Import Module…

Navigate to the directory where you cloned the Mobile SDK repository, expand the Machine directory, and you should see a project called “SalesforceSDK” with the IntelliJ logo next to it.

4

Select it and click OK. On the next screen, make sure the option to import from an external model is selected and the Eclipse list item is highlighted. Click Next, then click Next again on the following screen without making any changes. When you reach the final screen, check the box next to SalesforceSDK and click Finish. IntelliJ will now import the Eclipse project (Salesforce SDK) into your project as a project.

Now you can command the Salesforce Mobile SDK. Go to “File” -> “Project Structure…“, under “Project Settings” select “Facets”, now select the project with Salesforce SDK in brackets. Make sure the [Library Modules] box [IMG] is checked. Now, select the other one, then select the “Packaging” tab, and make sure the “Enable manifest merging” box is checked.

5

Next, select Modules from the Project Settings list, then select the SalesforceSDK module. Under the “Dependencies” tab, there should be a project with red text. Right click and delete it. From there, click on < your module name >; under the Dependencies tab, click the green “+”, select “Module Dependencies…”, the Salesforce SDK should be Your only option, click OK. Now select Apply in the Project Structure window and click OK.

6

Call a phone

Create a file called bootconfig.xml in res/values/; the contents of the file should look like this:

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <string name="remoteAccessConsumerKey"> YOUR CONSUMER KEY </string>
    <string name="oauthRedirectURI"> YOUR REDIRECT URI </string>
    <string-array name="oauthScopes">
        <item>chatter_api</item>
    </string-array>
    <string name="androidPushNotificationClientId"></string>
</resources>

Remember the connected app we created earlier? Here you will find the consumer key and redirect (callback) uri.

Out of curiosity, despite the fact that we specify the refresh_token on the OAuth Scopes server side, we don’t need to define it here. The reasoning behind this is that accessing the platform from a native app always requires this scope, so the Mobile SDK includes it automatically.

Next, make sure your String.xml file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="account_type">com.salesforce.samples.templateapp.login</string>
<string name="app_name"><b>Template</b></string>
<string name="app_package">com.salesforce.samples.templateapp</string>
    <string name="api_version">v30.0</string>
</resources>

The above values should be unique to your app.

Now create another class called KeyImpl.

public class KeyImpl implements KeyInterface {

    @Override
    public String getKey(String name) {
        return Encryptor.hash(name + "12s9adpahk;n12-97sdainkasd=012", name + "12kl0dsakj4-cxh1qewkjasdol8");
    }
}

Once this is done, create an arbitrary activity with a corresponding layout that extends SalesforceActivity and populate it as follows:

public class TutorialApp extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        SalesforceSDKManager.initNative(getApplicationContext(), new KeyImpl(), TutorialActivity.class);

/*
* Un-comment the line below to enable push notifications in this app.
* Replace 'pnInterface' with your implementation of 'PushNotificationInterface'.
* Add your Google package ID in 'bootonfig.xml', as the value
* for the key 'androidPushNotificationClientId'.
*/
        // SalesforceSDKManager.getInstance().setPushNotificationReceiver(pnInterface);
    }
}

This is the application entry point where we initialize the SalesforceSDKManager.

From the Salesforce Mobile SDK Developer’s Guide:

“The top level SalesforceSDKManager class implements password functionality for applications that use passwords and fills in the blanks for applications that do not. It Also sets up the login phase, cleans up after logout, and provides a special event observer that notifies your application when a system-level account is deleted. The OAuth protocol is used internally The class handles it automatically.”

For this tutorial, our corresponding layout is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical" android:layout_width="match_parent"
              android:layout_height="match_parent" android:background="#454545"
              android:id="@ + id/root">

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@ + id/data_display"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Fetch Data"
        android:id="@ + id/button"
        android:layout_gravity="bottom"
        android:onClick="onFetchClick"/>
</LinearLayout>

As you can see above, for the purposes of this tutorial, we’ve kept things pretty simple. A button to make a call and a textbox to display it.

Before going into the implementation details, I would like to mention the key points of the manifest file.

Since we have a new application entry point, in our case TutorialApp , we need to let the system know about it by defining it in the manifest.

7

If this step is missed, the application will crash with a runtime error complaining that you did not make an appropriate call to SalesforceSDKManager.init()

After doing this, your application should work fine

Now we’ll write the function to make the actual request. The following method will go into the activity created above.

private void sendRequest(RestRequest restRequest) {
        client.sendAsync(restRequest, new RestClient.AsyncRequestCallback() {

            @Override
            public void onSuccess(RestRequest request, RestResponse result) {
                try {

                    //Do something with JSON result.
                    println(result); //Use our helper function, to print our JSON response.

                } catch (Exception e) {
                    e.printStackTrace();
                }

                EventsObservable.get().notifyEvent(EventsObservable.EventType.RenditionComplete);
            }

            @Override
            public void onError(Exception e) {
                e.printStackTrace();
                EventsObservable.get().notifyEvent(EventsObservable.EventType.RenditionComplete);
            }
        });
    }

The above code will execute the RestRequest object passed to it and return the result asynchronously.

Let’s construct a RestRequest object for the client to execute:

First, we need a few helper methods to help construct HttpEntities

private Map<String, Object> parseFieldMap(String jsonText) {
        String fieldsString = jsonText;
        if (fieldsString. length() == 0) {
            return null;
        }

        try {
            JSONObject fieldsJson = new JSONObject(fieldsString);
            Map<String, Object> fields = new HashMap<String, Object>();
            JSONArray names = fieldsJson.names();
            for (int i = 0; i < names. length(); i ++ ) {
                String name = (String) names. get(i);
                fields. put(name, fieldsJson. get(name));
            }
            return fields;

        } catch (Exception e) {
            Log.e("ERROR", "Could not build request");
            e.printStackTrace();
            return null;
        }
    }



    private HttpEntity getParamsEntity(String requestParamsText)
            throws UnsupportedEncodingException {
        Map<String, Object> params = parseFieldMap(requestParamsText);
        if (params == null) {
            params = new HashMap<String, Object>();
        }
        List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
        for (Map.Entry<String, Object> param : params.entrySet()) {
            paramsList.add(new BasicNameValuePair(param.getKey(),
                    (String) param. getValue()));
        }
        return new UrlEncodedFormEntity(paramsList);
    }

Next, we define the methods that will generate the required RestRequest objects.

private RestRequest generateRequest(String httpMethod, String resource, String jsonPayloadString) {
        RestRequest request = null;

        if (jsonPayloadString == null) {
            jsonPayloadString = "";
        }
        String url = String.format("/services/data/%s/" + resource, getString(R.string.api_version)); // The IDE might highlight this line as having an error. This is a bug, the code will compile just fine.
        try {
            HttpEntity paramsEntity = getParamsEntity(jsonPayloadString);
            RestRequest.RestMethod method = RestRequest.RestMethod.valueOf(httpMethod.toUpperCase());
            request = new RestRequest(method, url, paramsEntity);
            return request;
        } catch (UnsupportedEncodingException e) {
            Log.e("ERROR", "Could not build request");
            e.printStackTrace();
        }
        return request;
    }

Finally, a helper method that prints our results. This is not strictly necessary, but it is included here

/**
 * Helper method to print object in the result_text field
 *
 * @param object
 */

    private void println(Object object) {
        if (resultText == null)
            return;

        StringBuffer sb = new StringBuffer(resultText. getText());
        String text;
        if (object == null) {
            text = "null";
        } else {
            text = object. toString();
        }
        sb.append(text).append("\
");
        resultText. setText(sb);
    }

Usage:

Remember the buttons we created earlier in the layout? Now we’re going to bring it to life.

public void onFetchClick(View view) {
        RestRequest feedRequest = generateRequest("GET", "chatter/feeds/news/me/feed-items", null);
        sendRequest(feedRequest);
    }

Now, run your application and if all goes well, you will be asked to enter your Salesforce credentials. You will then be asked to authorize the application you just created; click Allow and you will see your application.

When you press the button, it should dump all the JSON data from the request into the text field. It’s not pretty, but it gets the job done and illustrates the concept.

Now you can fetch this data, bind it to ListView or use to make other requests like “like” or “comment”.

Here’s a working sample app for reference:

  • https://github.com/incubator/SalesforceTutorialApp

Note:

I recommend using a library to parse JSON, such as Gson or Jackson. For the sake of understanding and continuity, we didn’t do that here as it’s much closer to everything you see in the Salesforce documentation and examples.

Resources

See these docs to learn about the many things you can do.

  • Salesforce Developer Platform – Mobile Resources
  • Chatter REST API Cheat Sheet (pdf)
  • Chatter REST API Documentation

have fun!

Translated from: https://www.javacodegeeks.com/2014/06/interfacing-salesforce-with-android.html