Java
Switch branches/tags
Nothing to show
Latest commit 8f67df6 Dec 3, 2014 @baobeimm baobeimm Merge pull request #27 from tstatler/readme-update
Updated readme with old docs from docs.appcelerator.com.
Permalink
Failed to load latest commit information.
acs
examples
.classpath
.gitignore
.project
LICENSE
README.md

README.md

This open source Java library allows you to integrate ACS into your Android application. Except as otherwise noted, the ACS Android SDK is licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)

Note: The ACS iOS SDK is no longer being developed or maintained. Please consider using the Appcelerator Platform Services SDK for iOS instead (Platform subscription required).

Getting Started: Using the Android SDK

The ACS Android SDK allows you to integrate Appcelerator Cloud Services into your Android application.

Setting up your environment

The ACS Android SDK works in any Android development environment. The following steps assume you are using Eclipse.

The first step is to clone the ACS Android SDK from GitHub.

Clone the ACS Android SDK:

git clone git@github.com:appcelerator/acs-android-sdk.git

Next, you'll create a new project in Eclipse for the ACS SDK.

Create a new project for the ACS SDK:

  1. In Eclipse, select File > New > Project.
  2. Select Android Project from Existing Code from the Android category, and click Next.
  3. Select the acs-android-sdk/acs directory. You should see the project properties populated.
  4. Click Finish.
  5. Open the Properties dialog for the project and select the Android category.
  6. In the Library section, enable the Is Library option. {@img is_library.png}
  7. Click OK

Now you can add the ACS project as a library of an existing project.

Add the SDK to an existing project

Once you've created the Android project for the SDK in your workspace, you can include the SDK as a library of an existing project.

To add the ACS Android SDK to an existing project:

  1. In the same workspace that contains the ACS Android SDK library project, open the Properties dialog for the project.
  2. Select the Android category.
  3. In the Library section, click Add.
  4. In the Project Selection dialog, select the ACS Android SDK library project. {@img add-library-dialog.png}
  5. Click OK.

You're now ready to use the SDK in your application.

Initialization and authorization

You use the `com.appcelerator.cloud.sdk.ACSClient` class to make API calls. First, you must import the ACSClient library into your application:

import com.appcelerator.cloud.sdk.ACSClient;

You need to authorize your application with Appcelerator Cloud Services using either an application key, or your OAuth consumer key/secret.

ACSClient sdk = new ACSClient("<app key>");
ACSClient sdk = new ACSClient("<OAuth consumer key>", "<OAuth secret>");

The ACS Android SDK also provides ability to store user session data in the device's local storage. This allows the application to restore a session after it is has been closed and then restarted. To enable this feature, pass an instance of the application's android.content.Context to the ACSClient constructor method as an additional parameter. You use the getApplicationContext() to get the application context.

If you are using an OAuth consumer key and secret:

ACSClient sdk = new ACSClient("<OAuth consumer key>", "<OAuth secret>", "<app. context>");

Or if you are using an application key to authorize:

ACSClient sdk = new ACSClient("<app key>", "<app. context>");

Session Management

As mentioned previously, when you create an ACSClient instance, lets you optionally store your application's session status in the device's local storage. The client also holds an instance of com.appcelerator.cloud.sdk.CCUser that contains the currently logged in user's information. The CCUser class has the following definition:

public class CCUser {
  public String getObjectId();  //id
  public Date getCreatedDate(); //created date
  public Date getUpdatedDate(); //updated date
  public String getFirst();     //first name
  public String getLast();      //last name
  public String getEmail();     //email
  public String getUserName();  //user name
}

You get an instance of this class by calling the getCurrentUser() method of the ACSClient class. If there is no current session or "logout" is called, the return value will be null.

Call the getCurrentUser() method of the ACSclient class; if there is no active session, or logoutUser() was called, the return value will be null.

Making API calls

The SDK provides the sendRequest() method to make synchronized REST calls to the ACS server easier. It has the following signature:

public CCResponse sendRequest(String url, CCRequestMethod method, Map<String, Object> data, boolean useSecure) throws ACSClientError

Parameters

url

The request API URL, which is a shortened version of the full REST URL. For instance, with the REST API you use http://api.cloud.appcelerator.com/v1/users/create.json to create a new user. In this case, you would use the value users/create.json for the url parameter.

method

Specifies the REST-ful method to use when making the method call. Accepts one of the following four objects from class com.appcelerator.cloud.sdk.CCRequestMethod as its value:

  • CCRequestMethod.GET
  • CCRequestMethod.POST
  • CCRequestMethod.PUT
  • CCRequestMethod.DELETE

data

An instance of Map<String, Object> which contains the parameters to pass. The key is the name of the passing parameter, and the value is the value of the passing parameter. For example, using the user login API:

Map<String, Object> data = new HashMap<String, Object>();
data.put("login", "test@appcelerator.com");
data.put("password", "test");

useSecure

Indicates whether the client should use SSL for HTTP communication. Set to true to use SSL, or false to a non-SSL connection.

Handling server responses

Server response are contained in an instance of com.appcelerator.cloud.sdk.CCResponse returned by the sendRequest() method. The CCResponse class has the following definition:

public class CCResponse {
  public CCMeta getMeta();
  public JSONObject getResponseData();
}

The getMeta() method returns an instance of com.appcelerator.cloud.sdk.CCMeta which contains all metadata returned by server. Here is the CCMeta's class definition:

public class CCMeta {
  public String getStatus();
  public int getCode();
  public String getMessage();
  public String getMethod();
}

The getResponseData() method returns an instance of class org.json.JSONObject which contains all of the response data returned by server. The ACS Android SDK uses the standard JSONObject class to wrap the returned JSON data.

Example of accessing a response object

The code below demonstrates how to handle an array users returned by the users/search.json method :

CCResponse response = sdk.sendRequest("users/search.json", CCRequestMethod.GET, null, false);
JSONObject responseJSON = response.getResponseData();
JSONArray users = responseJSON.getJSONArray("users");
for (int i=0;i<users.length();i++) {
  JSONObject user = usersArr.getJSONObject(i);
  System.out.println("User: " + user);
}

Push Notifications

ACS supports Google Cloud Messaging (GCM) for sending notifications to Android clients. This section describes how to integrate GCM notifications into your Android application with ACS.

Obtaining a Google API key and GCM sender ID

To use GCM in your Android application, you need to create a Google API project, enable its GCM service, and obtain the API project's Google API key and GCM sender ID. For steps on obtaining these items see Setting up Google Cloud Messaging.

Setup the Android Project

Next you need to add the ACS PushService service to your Android project's manifest file.

  1. Open your project's AndroidManifest.xml file.
  2. Add following to the <application> section:
    <service android:name="com.appcelerator.cloud.push.PushService" />
    
  3. Add following to the <manifest> section:
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
  4. Save your changes to AndroidManifest.xml.

Device Token

A device token is a unique identifier for an Android device. The push notification server can locate and push the desired notifications to the right device. You request a device token from the Appcelerator Cloud Services push notification server by calling one of following methods from the com.appcelerator.cloud.push.CCPushService class:

public static String getDeviceToken(final Context androidContext, final String appKey);
public static void getDeviceTokenAsnyc(final Context androidContext, final String appKey, final DeviceTokenCallback callback);

As their method names suggest, the difference between these methods is that getDeviceToken() operates synchronously, where the getDeviceTokenAsnyc() is asynchronous.

  • androidContext -- The instance of android.context.Context from your app
  • appKey -- The app's key of your Appcelerator Cloud Services app
  • callback -- An instance of com.appcelerator.cloud.push.DeviceTokenCallback for which whenever a device token is available, its receivedDeviceToken will be called.

Once you get the device token, you may proceed to subscribe the device by using the {@link PushNotifications#subscribe} API. This starts the push notification service and gets the Android device ready to receive push notifications.

Note: once device token is successfully acquired, it will be stored on the device's local storage, and next time when getting device token, it will return from reading local storage instead of communicating with server. So it is safe to request device token multiple times if necessary.

Push Notification Service

The push notification service is a standard Android service that keeps a persistent connection to the push notification server. Once the service is started, the device is ready to receive push notifications. The service continues running as a background process even if app is not actively running. The class com.appcelerator.cloud.push.CCPushService is a utility for starting and stopping the push notification service.

To start or stop the push notification service:

/* Start push notification service */
CCPushService.getInstance().startService(context);
/* Stop push notification service */
CCPushService.getInstance().stopService(context);

The context is the instance of android.content.Context which belongs to your Android app.

Please be noted that you need to get device token before starting the push notification service on your device, otherwise, there will be an exception thrown when trying to start push notification service without having a valid device token.

Receiving push notifications

Once your application has acquired the device token, and started the push notification service, the device is ready to receive push notifications. When a push notification arrives, there will be an application-wide broadcast containing the notification payload.

To process a push notification, your application must implement an Android receiver to receive the payload, and register the receiver in your project's AndroidManifest.xml file.

Below is an example of a receiver. The payload is a string that's passed to your receiver as an extra data field in the Intent parameter.

import com.appcelerator.cloud.push.PushService;

public class CustomReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    if(intent == null || context == null)
      return;
    if (intent.getAction().equals(PushService.ACTION_MSG_ARRIVAL)) {
      String payloadString = intent.getStringExtra("payload");
      // Covert payload from String to JSONObject
      JSONObject payload = null;
      try {
        payload = new JSONObject(payloadString);
      } catch (JSONException ex) {
        //error
      }
      ...
    }
  }
}

You must also register the receiver in the <application> section of your project's AndroidManifest.xml:

<receiver android:name="com.your.app.CustomReceiver" >
  <intent-filter>
    <action android:name="com.appcelerator.cloud.push.PushService.MSG_ARRIVAL" />
    <category android:name="android.intent.category.HOME" />
  </intent-filter>
</receiver>

Using the default broadcast receiver

The ACS Android SDK includes a fully-featured notification receiver that you can use in your project, instead of creating your own from scratch. The default notification receiver can take one of the following actions when a notififcation arrives:

  • Show a custom alert
  • Display custom title
  • Display custom icon
  • Display custom badge
  • Play a custom sound
  • Vibrate the device

Your application can invoke any of these actions simply by setting specifically named fields in the notification's JSON payload. First, you must register the default notification recevier in the <application> section of your project's AndroidManifest.xml file, as shown below.

<receiver android:name="com.appcelerator.cloud.push.PushBroadcastReceiver" >
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <action android:name="android.intent.action.USER_PRESENT" />
    <action android:name="com.appcelerator.cloud.push.PushService.MSG_ARRIVAL" />
    <category android:name="android.intent.category.HOME" />
  </intent-filter>
  <meta-data
    android:name="com.appcelerator.cloud.push.BroadcastReceiver.ArrivalActivity"
    android:value="com.yourorganization.pushnotifications.ArrivalActivity" />
</receiver>

When the device receives a push notification and has been processed by the default receiver, the ACSClient needs an Activity from your application to hand processing control to. The <meta-data/> element registers your custom Activity. The name attribute of the <meta-data/> section must be com.appcelerator.cloud.push.BroadcastReceiver.ArrivalActivity for the receiver to locate your activity, and its value attribute must point to your custom Activity.

The complete payload is passed to your Activity so that your application still further process the payload data, as necessary. Below is an example of an custom activity getting access to the notification payload:

public class ArrivalActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.arrival);
    Intent intent = getIntent();
    String payload = intent.getExtras().getString("payload");
    ...
  }
}

To invoke the desired behavior of the default receiver, the JSON notification payload must use certain reserved keywords, defined in the following table.

Key Value type Comments
alert String Content of the notification item to be displayed in notification center.
title String Title of the notification item to be displayed in notification center.
icon String The icon's file name without extension. This icon will be used to show in notification bar and be used as icon of notification item in the notification center. The file must be located in your project's res/drawable directory. If an icon file is not specified, or the specified file cannot be located, then app's default icon is used instead.
badge Number The number to display as the badge of the application icon.
sound String The sound's file name. The file should be located under app's assets/sound directory. If the sound file is not reachable, no sound will be played.
vibrate Boolean If the value is true, then the device will vibrate for 1 second.

Below an example JSON payload including all the reserved keywords with custom content:

{
  "title": "Example",
  "alert": "Sample alert",
  "icon": "little_star",
  "badge": 3,
  "sound": "door_bell.wav",
  "vibrate": true,
  "score": 51,
  "custom_field": {
    "headlines": "Appcelerator Cloud Services Rocks!"
  }
}

It's recommended to only have one push notification receiver registered at a time. Registering multiple receivers at the same time may cause conflicts.

Extending the default ACS receiver

You can extend the default notification's receiver implementation with your own functionality. To do this, you create your own broadcast receiver, as explained in the "Receiving push notifications" section above. In your custom receiver's onReceive() handler, extract the JSON payload and pass it to the ACSClient's showNotification() method to invoke the default receiver's behavior (for example, playing an audio file or displaying a message).

There are two versions of the showNotification() method. One takes two parameters: the Android application context and the JSON payload. The second version takes these two parameters and a notification ID (an integer) that lets you control how or if multiple notifications are merged into a single item in the Android notification center.

protected void showNotification(Context context, JSONObject payload);
protected void showNotification(Context context, JSONObject payload, int notificationId);

Parameters

  • context -- The android.content.Context that belongs to your app.
  • payload -- The JSONObject containing the notification payload.
  • notificationId -- An integer that identifies the notification. Notifications that share the same ID are merged into a single item in the Android notification center.

Remember to remove the default receiver from the AndroidManifest if you register your own receiver.

Photo Uploads

To upload a photo with the Android ACS SDK you create an instance of java.io.File, then pass the instance as an item of the data to the sendRequest() method.

The File instance must be initialized with an existing file.

Here is an example of uploading a local image file to ACS server through Android SDK:

1. Create a File instance:

// Create a File instance
File file = new File("/photos/profile.gif");
// Upload the image file by calling sendRequest:
ACSClient sdk = new ACSClient('vw1G7wq6KTKd52m76XwjvoiIhxeHxeXG');
Map<String, Object> data = new HashMap<String, Object>();
data.put("photo", file);
sdk.sendRequest("photos/create.json", CCRequestMethod.POST, data, false);

It is the client code's responsibility to make sure the instance of File is initialized with an existing local image file before passing to SDK, otherwise, the upload won't be succeed.

Example

Below is an example of creating a user by using the ACS Android SDK with a profile photo.

First, prepare the data object to pass to the sendRequest() method.

// Prepare new user data:
Map<String, Object> data = new HashMap<String, Object>()
data.put("email", "test@appcelerator.com");
data.put("first_name", "test_firstname");
data.put("last_name", "test_lastname");
data.put("password", "test_password");
data.put("password_confirmation", "test_password");

// Prepare new user profile image:
File file = new File("/photos/profile.gif");
data.put("photo", file);

Next, create an ACSClient instance and send the request.

ACSClient sdk = new ACSClient('vw1G7wq6KTKd52m76XwjvoiIhxeHxeXG');
CCResponse response = sdk.sendRequest("users/create.json", URLRequestMethod.POST, data, false);

When the sendRequest() method returns, process the server response. In this case, the new user's information is logged to the system console.

JSONObject responseJSON = response.getResponseData();  //CCResponse response
CCMeta meta = response.getMeta();
if("ok".equals(meta.getStatus())
    && meta.getCode() == 200
    && "createUser".equals(meta.getMethod())) {
  JSONArray users = responseJSON.getJSONArray("users");
  JSONObject user = users.getJSONObject(0);

  StringBuffer sb = new StringBuffer();
  sb.append("Create user successful!\n");
  sb.append("id:" + user.getString("id") + "\n");
  sb.append("first name:" + user.getString("first_name") + "\n");
  sb.append("last name:" + user.getString("last_name") + "\n");
  sb.append("email:" + user.getString("email") + "\n");
  System.out.println(sb.toString());
}

Run the ACS Demo sample application

Below are instructions for creating and running the Demo sample using Eclipse. The sample application uses the Google Maps v2 API to display location data. To build the application you will need to install Google Play services and add it to your project as a library. You'll also need to generate an API key for the Google Maps Android API v2 service.

Importing and setting up the Demo application:

  1. In Eclipse, select File > Import....
  2. Select Existing Android Code into Workspace from the Android category folder and click Next.
  3. Click Browse... and select the acs-android-sdk/examples/Demo folder.
  4. Click Finish.
  5. Open the Properties dialog for the project and, in the Android section, add Google Play Services as a library. {@img play-services-lib.png}
  6. Click OK to apply your changes.
  7. Open examples/Demo/res/layout/main.xml.
  8. Locate the <com.google.android.maps.MapView/> section of the file update the android:apiKey with your Google Maps API key, for example:
    android:apiKey="1234567890abcdefghijklmnop"
  9. Open DemoApplications.java located in the src/ folder.
  10. Locate the APP_ID constant and assign to it your ACS application ID, for example:
    public static final String APP_ID = "7YGry9R7abckXFG3ZYPAvQtA3TVBRH4T";
  11. In the initialize() method, uncomment the following line to construct the ACSClient using API_ID.
    sdk = new ACSClient(APP_ID, appContext);
  12. Save your changes.

Run the application:

  1. Create an appropriate Android virtual device (AVD):
  2. In Eclipse, create a Android run configuration that targets the AVD you created.
  3. Launch the run configuration to run the application in the simulator.

3-Legged OAuth process

Android SDK 2.1.1 and later supports interactions with Authorization Server. It provides APIs for Android application developers to sign in/sign up/sign out users with Authorization Server. For signing-in and signing-up the SDK uses a webview to load pages from Authorization Server.

1. Create a ACSClient object

To create a ACSClient object use one of the following constructors:

ACSClient sdk = new ACSClient(appConsumerKey);
ACSClient sdk = new ACSClient(appConsumerKey, appContext);
ACSClient sdk = new ACSClient(appConsumerKey, appContext, APIhost);
ACSClient sdk = new ACSClient(appConsumerKey, appConsumerSecret);
ACSClient sdk = new ACSClient(appConsumerKey, appConsumerSecret, appContext);
ACSClient sdk = new ACSClient(appConsumerKey, appConsumerSecret, appContext, APIhost);

If appConsumerSecret is not passed in the SDK will fail to sign requests. appContext is an android.content.Context object. APIhost is used to specify the ACS API server. The default is api.cloud.appcelerator.com/v1/.

To use 3-Legged OAuth you need to call the following method of the sdk object after it's created.

sdk.useThreeLegged(true);

Once get the sdk object you may call the following method to set the Authorization Server host other than the default.

sdk.setAuthHost("<AUTH HOST OTHER THAN DEFAULT>");

2. Check Session Status

The SDK doesn't take care of saving token information. Application Developers need to take care of saving token information somewhere and set it (and check its validity) to the sdk object upon application restart.

3. Sign in

Use one of the following methods to sign an user in.

sdk.authorize(Activity activity, String action, final DialogListener listener);
sdk.authorize(Activity activity, String action, final DialogListener listener, boolean useSecure);

activity: (android.app.Activity) The Android activity relevant.
action: (String) Should be ACSClient.ACTION_LOGIN.
useSecure: (Boolean) Specify if HTTPS should be used for sending request. If not specified default to false.
listener: (com.appcelerator.cloud.sdk.oauth2.DialogListener) The listener object is used to provide various callbacks to the signing-in process. Please refer to the Listener for more detail. The most significant callback method is onComplete(Bundle values) where you can get token information by calling the following methods and save them as you want.

sdk.getAccessToken();
sdk.getAccessExpires();

The following code from the demo application shows a call to this method.

sdk.authorize(UserView.this, ACSClient.ACTION_LOGIN, new LoginDialogListener(), false);

4. Sign up

Use one of the following methods to sign an user up.

sdk.authorize(Activity activity, String action, final DialogListener listener);
sdk.authorize(Activity activity, String action, final DialogListener listener, boolean useSecure);

activity: (android.app.Activity) The Android activity relevant.
action: (String) Should be ACSClient.ACTION_SINGUP.
useSecure: (Boolean) Specify if HTTPS should be used for sending request. If not specified default to false.
listener: (com.appcelerator.cloud.sdk.oauth2.DialogListener) The listener object is used to provide various callbacks to the signing-up process. Please refer to the Listenr class for more detail. The most significant callback method is onComplete(Bundle values) where you can get token information by calling the following methods and save them as you want.

sdk.getAccessToken();
sdk.getAccessExpires();

The following code from the demo application shows a call to this method.

sdk.authorize(UserView.this, ACSClient.ACTION_SINGUP, new LoginDialogListener());

5. Sign out

Signing-out should be done the same way as before. That is calling sdk.sendRequest to send a request to users/logout.json.

6. Login to API Server directly

To use the new authorization flow, you need to configure your app on Apps page. If an app is configured to use Authorization Server for user authentication, it's not possible to log-in/sign-up to API server directly.

7. Customize webview

The webview is used to show pages loaded from Authorization Server. It's possible to customize it. The SDK has the following method to accept a com.appcelerator.cloud.sdk.oauth2.DlgCustomizer object to support customization.
sdk.setDlgCustomizer(new MyDlgCustomizer());

For example, the following code snippet from the demo application implements a DlgCustomizer named MyDlgCustomizer.

public class MyDlgCustomizer implements DlgCustomizer {

    static final int FB_BLUE = 0xFF6D84B4;
    static final int MARGIN = 4;
    static final int PADDING = 2;

    public float[] getPortraitDimensions() {
        return new float[]{320, 420};
    }

    public float[] getLandscapeDimensions() {
        return new float[]{460, 260};
    }

    public TextView setUpTitle(Context context) {
        Drawable icon = context.getResources().getDrawable(R.drawable.application_icon);
        TextView title = new TextView(context);
        title.setText("ACS - To be customized");
        title.setTextColor(Color.WHITE);
        title.setTypeface(Typeface.DEFAULT_BOLD);
        title.setBackgroundColor(FB_BLUE);
        title.setPadding(MARGIN + PADDING, MARGIN, MARGIN, MARGIN);
        title.setCompoundDrawablePadding(MARGIN + PADDING);
        title.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
        return title;
    }

}

Have Fun!

LICENSE

This project is open source and provided under the Apache Public License (version 2). Please make sure you see the LICENSE file included in this distribution for more details on the license.

(C) Copyright 2012-2014, Appcelerator Inc. All Rights Reserved.