Janrain: User management platform for the social web

Janrain Engage for Android Developer's Guide

Before You Begin

  • You need to have created a Janrain Engage application
  • If you would like to do server-side authentication, you will need to create a token_url

Additional Documentation:

Introduction

Getting the Library

Using the Library



Introduction


User Experience

Sign In

The Janrain Engage for Android library gives your application the ability to authenticate users through their existing social identity provider accounts — e.g., Google, Facebook, Twitter, etc. When you are ready to authenticate a user, the library starts a new activity displaying a list of the providers that you configured in your Engage application. The user can select his desired provider and sign in through the provider's web interface. The library remembers his preference for a better return experience.

Below are some screen shots demonstrating the sign-in process.

Android Screen Shots

For an example application demonstrating authentication with the Engage for Android library, the Janrain Quick Sign-In* app is available for free on the Android Market.

Social Sharing

Additionally, the Engage for Android library includes a social sharing API, giving your users the ability to share their activities on several social networks. You can compose an activity, and when you are ready, the library displays an activity that allows your users to add their comments and share the activity. They can post it to a number of social providers, as well as share it through email and SMS.

Below are some screen shots demonstrating social sharing.

Android Screen Shots

For an example application demonstrating how you can share an activity with the Engage for Android library, the Janrain Quick Share* app is available for free on the Android Market.

* The Quick Sign-In and Quick Share applications are free and the source code for both applications ships with the library.

Components

The following components surround and interact with the Engage for Android library:
  • An Android application*
  • The Janrain Engage for Android library
  • The Engage server (rpxnow.com)
  • Sign-in and social sharing providers — e.g., Google, Facebook, Twitter, etc.
  • An optional web service* with an auth_info token URL
* Samples come with library

Sign-In Flow

  1. Your Android application requests the Engage authentication activity.
  2. The user chooses a provider.
  3. The library takes the user to the provider in an embedded web browser where she signs in.
  4. Janrain Engage completes authentication and sends the auth_info token, the user's authentication information, and the user's unique identifier back to the library.
  5. The library finishes the authentication activity and passes the profile data to the calling application.
  6. Optionally, the library can post the auth_info token to a token URL to complete server-side authentication:
    1. If you would like to do server-side authentication, you'll need to create a token URL. (See also, Janrain's sample code.)
    2. The library opens an HTTP/S connection to the token URL, in which:
      1. The library POSTs the auth_info token to the token URL.
      2. Your token URL server POSTs to the Engage auth_info url with the supplied auth_info token and your Engage API key. You may also make additional calls against the Engage API.
      3. The Engage server will respond to your server with the user's authentication information and the user's unique identifier.
      4. Your token URL server then creates a session tied to the user's identifier, and responds to the library with a session token.
    3. The response from your server's token URL, containing the session token you created, is passed to your JREngageDelegate via the jrAuthenticationDidReachTokenUrl method.
    4. Your mobile application stores the session token supplied in the token URL's response, and uses it to communicate securely with your web service — to conduct purchases, access user data, or perform other sensitive transactions.
  7. The application parses the profile data and the user is signed in.

Sharing Flow

  1. The application creates an activity object and populates the object's fields.
  2. The application initiates social sharing, passing the activity object to the library.
  3. The user can add comments and choose which provider he wishes to share the activity with.
  4. If the user is already signed in, he can post the activity to the provider.
  5. If the user is not signed in, the library takes the user to the provider's web interface where he authenticates, and then the activity is shared.
  6. The user can share to multiple providers, and the dialog is closed when the user presses the back button.


Getting the Library


Prerequisites


Download the Library

You can either:
  • Download an archive of the library, or
  • clone the Janrain Engage for Android library from GitHub:

    git clone git://github.com/janrain/engage.android.git

We recommend that you clone the GitHub repository, and checkout the master branch. master is the stable branch with all the latest bug fixes. By using git to clone the repository it's easy to keep up with bug fixes — just run git pull.


Add the Library to Your Android Eclipse Project

  1. Ensure that the Android ADT plug-in is installed
  2. Select File → Import
  3. Select Existing Projects into Workspace, click Next
  4. Click Browse, browse to .../engage.android/JREngage, click Open
  5. Click Finish
  6. Select your project in the Package Explorer
  7. Open the Project menu, select Project → Properties
  8. Select Android in the left list
  9. In the Library section click Add...
  10. Select JREngage, click OK
  11. Select Java Build Path in the left list
  12. Select the Libraries tab
  13. Click Add JARs...
  14. Select android-support-v4.jar, then click OK
  15. Select the Order and Export tab
  16. Ensure that the two Jackson Jars are listed above the JREngage_src path
  17. Your project should now build and run

Further IDE support is available via the Engage for Android support forum.


Add the Library to Your Android IntelliJ Project

  1. In the project pane, right click a module and select Open Module Settings
  2. In the leftmost pane, under Project Settings, select Modules
  3. Set the Project SDK to Android 3.2 or higher (your project is still deployable to Android 1.6+. This setting controls the Android SDK against which your project is compiled. It does not control the Android version your project targets. You may still target down to Android 1.6.
  4. Add a module by clicking the + button, just to the right of the Project Settings pane
  5. Select New → Module
  6. Select Import existing module
  7. Click the file chooser button (...), browse to the JREngage.iml file found under engage.android/JREngage/JREngage.iml, then click Finish
  8. In the list of modules (the second pane from the left, to the right of the project settings pane), expand the JREngage module folder (don't worry if it's underlined and red; this will go away shortly)
  9. Click the Android facet, immediately below the JREngage folder
  10. Ensure that Is Library Project is selected
  11. In the list of modules (second pane from the left), select your application's module
  12. Select the Dependencies tab
  13. of your application's module
  14. At the bottom of the Dependencies pane click the + button, and then choose Module Dependency
  15. Select JREngage, click OK. Ensure that the new dependency's Scope is set to Compile
  16. Under Project Settings, click Libraries
  17. Add a library by clicking the + box just to the right of the Project Settings pane, then choose Java in the New Project Library popup window.
  18. Browse to .../engage.android/JREngage/libs, then select android-support-v4.jar
  19. In the Choose modules dialog, click Cancel. (The library dependency already exists; the library only needs to be defined.) Ensure that library is still created even though you click cancel
  20. Ensure that the new library's name is "android-support-v4"
  21. Click OK to close the Project Structure settings window

Further IDE support is available via the Engage for Android support forum.

Troubleshooting Build and Runtime errors

engage.android/JREngage/res/values-v11/styles.xml:3: error: Error retrieving parent for item: No resource found that matches the given name '@android:style/Theme.Holo.Light.DialogWhenLarge.NoActionBar'.
Ensure that the project build SDK is Android API level 13 or higher. Note that this setting is different than the targeted API level. See the IDE setup instructions, or message us on the support forum for more help with this.
engage.android/JREngage/src/com/janrain/android/engage/ui/JRUiFragment.java
package android.support.v4.app does not exist
Ensure that the "android-support-v4" library is defined in your IDE and that it references the engage.android/JREngage/libs/android-support-v4.jar jar.
package com.janrain.android.engage.net.async does not exist
Try cleaning and rebuilding your project. If you are compiling with Eclipse close and restart Eclipse.


Using the Library


Use the Engage for Android library in three steps:

  1. Declare the library project dependency and add the required elements to your AndroidManifest.xml file
  2. Initialize the library.
  3. Begin authentication or sharing by calling one of the two show...Dialog methods.

Quick Start Guide

To begin, sign in to Engage and configure the providers you wish to use for authentication and/or social sharing. You will also need your 20-character Application ID from the Engage Dashboard.


Declare and Import

Copying from .../engage.android/JREngage/AndroidManifest.xml, add the following bolded XML elements* to your project's AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="13" />

  ...

  <application ... >

  ...


    <activity
        android:name="com.janrain.android.engage.ui.JRFragmentHostActivity"
        android:configChanges="orientation|screenSize"
        android:theme="@style/jr_dialog"
        android:windowSoftInputMode="adjustResize|stateHidden"
        />

    <activity
        android:name="com.janrain.android.engage.ui.JRFragmentHostActivity$Fullscreen"
        android:configChanges="orientation|screenSize"
        android:theme="@style/jr_fullscreen"
        android:windowSoftInputMode="adjustResize|stateHidden"
        />

    <activity
        android:name="com.janrain.android.engage.ui.JRFragmentHostActivity$FullscreenNoTitleBar"
        android:configChanges="orientation|screenSize"
        android:theme="@style/jr_fullscreen_no_title"
        android:windowSoftInputMode="adjustResize|stateHidden"
        />


  ...

  </application>

</manifest>

* The placement of the elements in the XML structure is important; the uses-permission element and the uses-sdk element must be placed as children of the manifest element, and the four activity elements must be children of the application element.

If you wish to target a version of Android lower than 13 (which is 3.2) you may. To do so, change the android:targetSdkVersion, to your desired deployment target. You must still build against API 13+ even when targeting a lower API level.


Import the following classes:

import com.janrain.android.engage.JREngage;
import com.janrain.android.engage.JREngageDelegate;
import com.janrain.android.engage.JREngageError;
import com.janrain.android.engage.net.async.HttpResponseHeaders;
import com.janrain.android.engage.types.JRActivityObject;
import com.janrain.android.engage.types.JRDictionary;

Initialize

Interaction begins by calling the JREngage.initInstance method, which returns a JREngage object:

private static final String ENGAGE_APP_ID = "<YOUR_APP_ID>";
private static final String ENGAGE_TOKEN_URL = "<YOUR_TOKEN_URL>";
private JREngage mEngage;
private JREngageDelegate mEngageDelegate = ...;

...

mEngage = JREngage.initInstance(this, ENGAGE_APP_ID, ENGAGE_TOKEN_URL, this);

The initInstance method takes four arguments, activity, appId, tokenUrl, and delegate:

  • activity (required) is your application's Android Activity from which the Engage for Android activities will be started.
  • appId (required) is the Application ID of your Janrain Engage application (found on the Engage Dashboard).
  • tokenUrl (optional) is the token URL that authentication from your application will post to.
  • delegate (optional) is an implementation of the JREngageDelegate interface through which you can receive responses and event information from the library.

Social Sign-In

Once the JREngage object has been initialized, user authentication can be started by calling the showAuthenticationDialog method.

mEngage.showAuthenticationDialog();

To receive the user's basic profile data, implement the jrAuthenticationDidSucceedForUser method of JREngageDelegate:

public void jrAuthenticationDidSucceedForUser(JRDictionary auth_info, String provider) {
  JRDictionary profile = auth_info.getAsDictionary("profile");
  String displayName = profile.getAsString("displayName");
  String message = "Authentication successful for user: " + displayName));

  Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}

Social Sharing

If you want to share an activity, first create an instance of the JRActivityObject:

  String activityText = "added JREngage to her Android application!";
  String activityLink = "http://janrain.com";

  JRActivityObject jrActivity = new JRActivityObject(activityText, activityLink);

Enrich the activity to be shared by populating some of the optional fields. Here an exciting Facebook action link is added:

  activityObject.addActionLink(new JRActionLink("Download the Quick Share demo!",
      "https://market.android.com/details?id=com.janrain.android.quickshare");

Then pass the activity to the showSocialPublishingDialogWithActivity method:

mEngage.showSocialPublishingDialogWithActivity(jrActivity);

Even Quicker Quick Start Guide

Just copy and paste!

  1. Sign in to Engage, create an application, and configure the providers you wish to use for sign-in and/or social sharing.
  2. Import the following classes:
    import com.janrain.android.engage.JREngage;
    import com.janrain.android.engage.JREngageDelegate;
    import com.janrain.android.engage.JREngageError;
    import com.janrain.android.engage.net.async.HttpResponseHeaders;
    import com.janrain.android.engage.types.JRActivityObject;
    import com.janrain.android.engage.types.JRDictionary;
    
  3. To authenticate*:
    JREngage mEngage =
        JREngage.initInstance(this, "<YOUR_APP_ID>", "<YOUR_TOKEN_URL>", this);
    
    mEngage.showAuthenticationDialog();
    
  4. To share*:
    JREngage mEngage =
        JREngage.initInstance(this, "<YOUR_APP_ID>", "<YOUR_TOKEN_URL>", this);
    
    mEngage.showSocialPublishingDialogWithActivity(new JRActivityObject(
        "added JREngage to her Android application!", "http://janrain.com"));
    
  5. Start with an empty implementation of the JREngageDelegate interface:
    JREngageDelegate mEngageDelegate = new JREngageDelegate() {
      public void jrEngageDialogDidFailToShowWithError(JREngageError error) { }
    
      public void jrAuthenticationDidSucceedForUser(JRDictionary authInfo,
                                                    String provider) { }
    
      public void jrAuthenticationDidReachTokenUrl(String tokenUrl,
                                                   HttpResponseHeaders response,
                                                   String tokenUrlPayload,
                                                   String provider) { }
    
      public void jrAuthenticationDidNotComplete() { }
    
      public void jrAuthenticationDidFailWithError(JREngageError error, String provider) { }
    
      public void jrAuthenticationCallToTokenUrlDidFail(String tokenUrl,
                                                        JREngageError error,
                                                        String provider) { }
    
      public void jrSocialDidNotCompletePublishing() { }
    
      public void jrSocialDidCompletePublishing() { }
    
      public void jrSocialDidPublishJRActivity(JRActivityObject activity,
                                               String provider) { }
    
      public void jrSocialPublishJRActivityDidFail(JRActivityObject activity,
                                                   JREngageError error,
                                                   String provider) { }
    };
    
  6. Add code to the interface methods you care about receiving, replace anything <between angle brackets>, and you're good to go!
* The first time your application uses Engage for Android, the library contacts the Engage servers to retrieve your application's list of providers and other configuration information. Once this has been downloaded, the library caches this information for subsequent use, updating the cache only when the information has changed (e.g., you add or remove a provider).

While you can initialize the JREngage library immediately before you call one of the show... methods, we recommend initializing the library as soon as your application is launched in order to allow the configuration information to be downloaded in the background so that it's available as soon as your user is ready to interact with the Engage for Android library. Otherwise, your user may encounter a loading screen while the configuration information is downloaded.

Server-side Authentication

If you would like to access any of the extra features available in the Janrain Engage API or if you would like to complete server-side authentication, do so by implementing a token URL as follows:

  1. Create a server side HTTP or HTTPS endpoint (preferably HTTPS). This will be your auth_info token URL, and mobile devices running your mobile app will POST an Engage auth_info token to this endpoint, in exchange for an access token for your web service.
  2. From the new endpoint, extract the token. It's POSTed in a parameter named token.
  3. Call auth_info. Supply the token just received, and your application's 40-character Engage API key.
  4. Process the profile data returned from auth_info, and log your user in to your web application. (The unique and secure key you should use to identify the user is the identifier field of the profile node.) As necessary create and return access tokens or session cookies in your endpoint's response. Your mobile app will receive that response.

    For example in Ruby on Rails, you might rely on the ActionController session and the cookie that it sets like so:

    # The following helper class is from the Engage sample code found at
    # https://github.com/janrain/Janrain-Sample-Code
    ENGAGE = Rpx::RpxHelper.new("your_api_key_here",
                                "http://rpxnow.com",
                                "your_engage_app_realm_here") # e.g. mytestapp
    
    # This is the Engage auth_info token URL -- the endpoint which spawns
    # new mobile user sessions.
    def mobileEngageSignIn
      auth_info = ENGAGE.auth_info(params[:token])
      
      identifier = auth_info['identifier']
    
      user = User.find_or_create_by_engage_identifier(identifier)
      # do other stuff, like populate the User record with the auth_info
    
      session[:user_id] = user.id
    end
    

    If you're using the Rails ActionController session, you should set the cookie expiration to an appropriate value for a mobile device:

      # This initializer block is found in app/config/environment.rb
      Rails::Initializer.run do |config|
        config.action_controller.session[:session_expires] = 10.years.from_now
      end
    

    Then, make sure that you save the cookie in your mobile app, e.g.:

    org.apache.http.cookie.Cookie[] mSessionCookies;
    
    public void jrAuthenticationDidReachTokenUrl(String tokenUrl,
                                                 HttpResponseHeaders responseHeaders,
                                                 String tokenUrlPayload,
                                                 String provider) {
        mSessionCookies = responseHeaders.getCookies();
    }
    

From your new auth_info token URL you can also access access other Engage features. For example, you could call get_contacts* and use the contact list returned to find other users of your mobile app that this user may know.

* Some features are limited to Pro, Plus, or Enterprise customers only.

To configure the library with your token URL, pass it to initInstance when initializing the library:

private static final String ENGAGE_APP_ID = "<YOUR_APP_ID>";
private static final String ENGAGE_TOKEN_URL = "<YOUR_TOKEN_URL>";
private JREngage mEngage;
private JREngageDelegate mEngageDelegate;

...

mEngage = JREngage.initInstance(this, engageAppId, engageTokenUrl, mEngageDelegate);

Alternatively, you can change the token URL at any time using the setTokenUrl method:

    JREngage mEngage;

    ...
    
    mEngage.setTokenUrl(newTokenUrl);

You may configure the library with a null or empty token URL, and this authentication step will be skipped.

Whether or not the library posts the token to the token URL, your Android application must not contain your Engage API key.


Email and SMS Sharing

You can also share your activity through email or SMS*. This feature uses the Android platform's Intent framework to start activities that your user can send pre-composed messages with.

To share with email or SMS, create a JREmailObject or a JRSmsObject, populate the object's fields, and then add the object to the mEmail or mSms property in your JRActivityObject. The given content is supplied in the Intent used to launch the email or SMS activity.

* Although, the actual transport of an email or SMS does not go through the Engage servers (it's delivered through the Android devices existing mail or SMS activity), Engage will track when an activity is shared via email or SMS.

Email

Create a JREmailObject and populate the fields of the object:

String emailSubject = "Check out this article from the Janrain Blog!";
String emailBody =
  "I found this article on Janrain's blog, and I thought you might be interested!\n";
emailBody +=
  "http://www.janrain.com/blogs/janrain-engage-social-login-and-sharing-your-android-apps";

JREmailObject email = new JREmailObject(emailSubject, emailBody);

Add the object to the your JRActivityObject and pass it to the library:

JRActivityObject activity =
  new JRActivityObject("shared an article from the Janrain Blog.",
  "http://www.janrain.com/blogs/janrain-engage-social-login-and-sharing-your-android-apps");

activity.setEmail(email);
engage.showSocialPublishingDialog(activity);

SMS

Create a JRSmsObject and populate the fields of the object:

String smsBody = "Check out this article from the Janrain Blog!\n";
smsBody +=
  "http://www.janrain.com/blogs/janrain-engage-social-login-and-sharing-your-android-apps";

JRSmsObject sms = new JRSmsObject(smsBody);

Add the object to the your JRActivityObject and pass it to the library:

JRActivityObject activity = new JRActivityObject("shared an article from the Janrain Blog.",
  "http://www.janrain.com/blogs/janrain-engage-social-login-and-sharing-your-android-apps");

activity.setSms(sms);
engage.showSocialPublishingDialog(activity);

URL Shortening

If your email or SMS message body contains URLs that you would like shortened to an http://rpx.me URL (with which you can track click-throughs), you can do so by setting the mUrls property of the JREmailObject, or the mUrls property of the JRSmsObject. The library will then contact the Engage servers to obtain up to five shortened URLs for email and SMS each, and then replace the URLs in the email and SMS message bodies.

To use URL shortening, create an email or SMS object, and populate the message and/or subject fields with your content, including the URLs that you would like shortened:

String emailSubject = "Check out this article from the Janrain Blog!";
String emailBody =
  "I found this article on Janrain's Blog, and I thought you might be interested!\n";
emailBody +=
  "http://www.janrain.com/blogs/janrain-engage-social-login-and-sharing-your-android-apps";
emailBody +=
  "\nFor more information check http://janrain.com";

JREmailObject email = new JREmailObject(emailSubject, emailBody);

String smsBody = "Check out this article from the Janrain Blog!\n";
smsBody +=
  "http://www.janrain.com/blogs/janrain-engage-social-login-and-sharing-your-android-apps";
smsBody +=
  "\nFor more information check http://janrain.com";

JRSmsObject sms = new JRSmsObject(smsBody);

activity.setEmail(email)
activity.setSms(sms);

Then, create a list of strings containing the exact URLs from the message body, and pass the list to JREmailObject#setUrls, or JRSmsObject#setUrls. Any URLs in the message body which are not in this list will not be shortened.

List<String> urls = new ArrayList<String>();
urls.add("http://www.janrain.com/blogs/social-login-iphone-janrain-engage");
urls.add("http://janrain.com");

email.setUrls(urls);
sms.setUrls(urls);

Once you pass the activity object to the library, it will contact the Engage servers to obtain shortened URLs for all the URLs that you provided in the URL lists. Once this connection returns, the library will replace any instance of your URLs in your email/SMS message body with the http://rpx.me URL. When a user clicks on any shortened URL, it will redirect them to the original URL and Engage will track the referral.

When obtaining the shortened URLs, the connection to the Engage server is made as soon as your application opens the library's sharing dialog. To maintain the best user experience, this call is non-blocking, but, if there are network latency issues, the connection may not return before the user is ready to share your activity via email/SMS. If the user does attempt to share the activity before the connection to shorten the URLs is returned, the shared activity will contain the original URLs and the click-throughs will not be tracked. As soon as the connection returns, the activity is modified to contain the shortened URLs.


Android Tablet Support

Since release 2.0 the Engage for Android library has included support for Android tablets. Tablet screens are supported either seamlessly or with embeddable fragments.

Seamless Support

To take advantage of seamless support simply continue to call JREngage#showAuthenticationDialog() or JREngage#showSocialPublishingDialogWithActivity(JRActivityObject). The library dialogs will be displayed modally.

Embedded Fragment Support

The Engage for Android sharing dialog may also be embedded in your UI as an Android Fragment. For a great example of this feature check out the Quick Share demo app when run on a tablet with an Android xlarge screen (e.g. a Motorola Xoom or a Samsung Galaxy Tab 10.)

  • To start a Fragment in a specific container call JREngage#showSocialPublishingFragment(...).
    There are two variants of showSocialPublishingFragment:
    • The simple form takes a JRActivityObject, a FragmentActivity, and an int which is the id of the FrameLayout in which to embed the sharing fragment.
    • The long form takes additional parameters, a boolean flag controlling whether the Fragment is added to the back stack, and four null-able Integers which configure standard or custom transitions and/or animation resources.
  • If you wish to get a Fragment you can manage yourself (e.g. to add it to the back stack), use JREngage#createSocialPublishingFragment(JRActivityObject)

NOTE: Embedded support requires a host activity sub-classed from android.support.v4.app.FragmentActivity. android.app.FragmentActivity is incompatible.


Additional Documentation


Janrain Engage for Android API

For the complete API of the Engage for Android library, please see our API documentation.

documentation.janrain.com

For release notes check the README, or go to the Engage for Android section of documentation.janrain.com.

Janrain Engage for Android Support Forum

Additional support can be found at the Engage for Android Support Forum.

Copyright © 2017 Janrain, Inc.