Skip to content

Tutorials

Suzie Hopkins edited this page Sep 16, 2020 · 12 revisions

This guide provides tutorials for working with the Community Android SDK API providers and utility methods.

Intro to the Client classes

When you work with our API providers and utility methods to interact with Khoros Community entities like users, messages, kudos, and images, you’ll generally be working with these classes:

  • LiClient
  • LiClientManager
  • LiClientRequestParams
  • LiPostClientResponse
  • LIGetClientResponse

We’ll give you a quick introduction to them here, as you’ll be seeing these throughout our tutorials.

LiClient is an interface that includes methods to make callbacks, get the HTTP request type, define the ordering of LiQL query responses, get the Gson library, and client type.

LiClientManager is the class that includes all of the API providers to interact with Community.You’ll be using this class to make POST, PUT, and GET actions for things like posting a message, giving a kudo, adding an image, creating a user, and so on. This class also includes methods for you to make custom POST, PUT, and GET actions. For custom POST and PUT actions, you will provide a Community API v2 endpoint path and a request body. For custom GET actions, you will provide a LiQL query.

LiClientRequestParams is a class that includes all of the request parameter builders used with our API providers. Each provider has a unique set of parameters, but all of them require the Android context. See API reference and Javadoc for details.

LiPostClientResponse represents the response to a POST action. The class includes methods to get the response, and to get specific details about the response like the HTTP code and status, and the JSON object if one is included.

LiGetClientResponse represents the response to a GET action. The class includes methods to get the response (transformed to the corresponding data model), and to get details like the HTTP code and status of the response.

Handling a 401 authentication error

If an anonymous user does not have permission to perform a certain action, such as replying to a message or giving kudos, the SDK returns a 401 (Unauthorized) error. The following example shows how to check for the 401 error and display the error in the UI.

try {
    LiClientRequestParams liClientRequestParams = new LiClientRequestParams.LiMessagesByBoardIdClientRequestParams(getContext(), selectedBoardId);
    LiClient client = LiClientManager.getMessagesByBoardIdClient(liClientRequestParams);
    client.processAsync(new LiAsyncRequestCallback < LiGetClientResponse > () {
        @Override
        public void onSuccess(LiBaseRestRequest liBaseRestRequest, final LiGetClientResponse liClientResponse) {
            if (!isAdded() || getActivity() == null) {
                return;
            }

            // check for a 401 Unauthorized error
            if (null != liClientResponse) {
                if (liClientResponse.getHttpCode() == HTTP_CODE_UNAUTHORIZED) {
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            showUserNotLoggedIn();
                        }
                    });
                    return;
                } else if (liClientResponse.getHttpCode() == HTTP_CODE_SERVER_ERROR) {
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //Show server error
                        }
                    });
                    return;
                }

                response = liClientResponse.getResponse();
                // show the UI based upon response in case of successful execution
            }
        }

        @Override
        public void onError(Exception e) {
            if (!isAdded() || getActivity() == null) {
                return;
            }
        }
    });
} catch (LiRestResponseException exception) {
    if (!isAdded() || getActivity() == null) {
        return;
    }
    //Show server error
}

Then you can use the following to begin the login flow for the anonymous user:

try {
 LiSDKManager.getInstance().initLoginFlow(getActivity(), ssoToken);
} catch (URISyntaxException e) {
 Log.d(LiSDKConstants.GENERIC_LOG_TAG, "Could not initiate login flow");
 LiUIUtils.showInAppNotification(getActivity(), R.string.li_login_failure);
}

Working with messages

This section provides a walkthrough of actions used when working with messages.

Post a topic message

Let’s look at an example class that posts a new topic message to the community. We’ll build a client using the API provider LiClientManager.getCreateMessageClient(LiClientRequestParams liClientRequestParams). Note that this example is for a new topic. Creating a reply takes other considerations. We show an example of creating a reply later on.

We need to:

  • Build the request parameters for the client
  • Create the client
  • Call the client

All of our clients take a set of request parameters, so the first thing we do is build those parameters to pass to the client. Client request parameters are built using LiClientRequestParams. There is a specific builder for each client. To post a new message, we need the Android context, the subject and body text, the board where the message will be posted, and (optionally) an image ID and title if the user has uploaded an image.

We build the request parameters like this:

// Build the parameters
LiClientRequestParams liClientRequestParams = new LiClientRequestParams.LiCreateMessageClientRequestParams(getContext(), askQuestionSubjectText,askQuestionBodyText, selectedBoardId, selectedImageId, selectedImageName);

Next, we create the client, passing our request parameters:

// Create the client
LiClient postQuestionClient = LiClientManager.getCreateMessageClient(liClientRequestParams);

In this example, we’re going to make an asynchronous call to run the client. The client will return a response, and we’ll use LiPostClientResponse to handle the response depending on the HTTP code returned.

// Call the client
postQuestionClient.processAsync(new LiAsyncRequestCallback<LiPostClientResponse>() {
    // If successful, use  HTTP response code from LiPostClientResponse
    @Override
    public void onSuccess(LiBaseRestRequest liBaseRestRequest, 
                        LiPostClientResponse liClientResponse) throws LiRestResponseException {
            
        switch (liClientResponse.getResponse().getHttpCode()) {
           // Depending on the HTTP code returned in the response, 
           // display the appropriate message post confirmation
           // and perform the next action
           case LiSDKConstants.HTTP_CODE_SUCCESSFUL:
                // Handle successful post
           case HTTP_CODE_FORBIDDEN:
                // Handle permission issue 
           default:
                // Handle other error codes
        }
    }
    @Override
    public void onError(Exception e) {
    	// Handle call failure
    }

});

Post a topic message with an image

Posting a topic with an image adds another layer to our topic post example. The flow requires that we upload the image to the community first. This returns an image ID. The provider uses the ID to create a macro string and appends that string to the end of the message body entered by the user.

You’ll upload the image to the community using LiClient getUploadImageClient, and you’ll build the request parameters with LiUploadImageClientRequestParams.

// Build the request parameters
LiClientRequestParams liClientRequestParams = new
            LiClientRequestParams.LiUploadImageClientRequestParams(getContext(),
            selectedImageName, imageDescription,imageAbsolutePath,selectedImageName);

// Create the client
LiClient uploadImage = LiClientManager.getUploadImageClient(liClientRequestParams);
            uploadImage.processAsync(new LiAsyncRequestCallback<LiPostClientResponse>() {

Next, we make a callback.

// Call the client
uploadImage.processAsync(new LiAsyncRequestCallback<LiPostClientResponse>() {
       // Get the image ID from the response
        @Override
        public void onSuccess(LiBaseRestRequest liBaseRestRequest,
                                      LiPostClientResponse liPostClientResponse)
                    throws LiRestResponseException {
               // If successful, upload the image the message
               // We can get the image ID from the JSON object returned with the response
               // using calls on LiPostClientResponse.
               // We get the ID as a string so that we can append it to the message body
               // in the next step
               if (liPostClientResponse.getHttpCode() == 200) {
                  Log.i(LiSDKConstants.GENERIC_LOG_TAG,
                                liPostClientResponse.getResponse().getData().toString());
                  selectedImageId = liPostClientResponse.getResponse().getData()
                                .get("data").getAsJsonObject().get("id").getAsString();
                  post();
               // If unsuccessful, do something else, 
               // like notify the user that the upload was unsuccessful
               } else {
                    ...
                    }
                }
     	}, imageAbsolutePath, selectedImageName);

Get a message

To retrieve a specific message, you’ll use the LiClientManager.getMessageClient(LiClientRequestParams liClientRequestParams) provider. Here’s an example.

We’re going to create and make a callback to run a client to get a message by ID. The provider returns the LiMessage object.

// Build the request parameters
LiClientRequestParams liClientRequestParams = new 
            LiClientRequestParams.LiMessageClientRequestParams(getContext(),
                selectedMessageId);
// Create the client
LiClient messageClient = LiClientManager.getMessageClient(liClientRequestParams);
// Call the client
messageClient.processAsync(new LiAsyncRequestCallback<LiGetClientResponse>() { 
     @Override
     public void onSuccess(LiBaseRestRequest request,
                           LiGetClientResponse originalArticleResponse)
                 throws LiRestResponseException {
          selectedMessage = (LiMessage) originalArticleResponse.getResponse().get(0);
          // do something with the message
          });
     }
     // If unsuccessful, handle the error
     ...

Post a reply

Before we can post a reply, we want to get and display the parent message. We showed an example of how to get the message earlier. While replies and topic messages are both stored as messages in the database, we create a reply using a different provider than when creating a topic.

To create a reply, we use LiClientManager.getCreateReplyClient. We’re passing the body text of the reply and the parent message ID to getCreateReplyClient, as well as in image ID and name if the user uploads an image.

// Build the request parameters
LiClientRequestParams liClientRequestParams = new
                      LiClientRequestParams.LiCreateReplyClientRequestParams(getContext(),
                      askQuestionBodyText, selectedMessageSubject, selectedMessageId, selectedImageId,
                      selectedImageName);
// Create the client
LiClient replyMessageClient = LiClientManager.getCreateReplyClient(liClientRequestParams);
// Call the client        
replyMessageClient.processAsync(new LiAsyncRequestCallback<LiPostClientResponse>() {
...
}

Just like when creating a topic message, we will use LiPostClientResponse.getResponse().getHttpCode() to get the HTTP response code to display the appropriate message post confirmation message and take the next actions.

Working with subscriptions

Subscriptions are a powerful way for users to stay engaged with a community. A subscription to a conversation, a board, a category, or even a label, alerts users to activity important to them.

This section will teach you how to integrate subscription operations into an Android application through Community SDK APIs.

A subscription operates on a target -- the community, a category, a board, a topic message, or a label -- and each target is represented by a unique identifier. Users subscribe or unsubscribe to a single target for each subscription they create in the community.

In the following sections, you'll learn how to:

Subscription API calls work similar to any other calls made through the Community Android SDK APIs. Each of the examples in this section includes the following tasks:

  • Creating a respective API-method client parameter
  • Creating a respective API-method client
  • Processing the client request, synchronously or asynchronously as needed
  • Processing the response

Verify that a user is logged in

All calls to our subscriptions API require authentication. Anonymous users cannot create or delete subscriptions.

Before you make any calls to the Subscription API, ensure that the current user is logged using this call on LiSDKManager:

LiSDKManager.getInstance().isUserLoggedIn() == true

Subscribe to a topic message

Let's walk through creating a subscription to a message. Note that users subscribe to topic messages, not to replies or comments.

Create a target

The first thing we're going to do is create a subscription target using LiSubscriptionPostModel.MessageTarget(messageId), passing the message ID of the topic we're subscribing to.

LiSubscriptionPostModel also supports LiSubscriptionPostModel.BoardTarget.

String messageId = "message:test";
LiSubscriptionPostModel.Target target = new LiSubscriptionPostModel.MessageTarget(messageId);

Create a subscription POST model

Next, we're going to create a subscription POST model. This step puts the details for the subscription into the proper model for ingestion by the API when we make our POST call. We pass the target we created in the previous step.

LiSubscriptionPostModel postModel = new LiSubscriptionPostModel(target);

Create a subscription parameter

Now, we create the parameters for the subscription that we will pass with our client request:

LiClientRequestParams.LiPostSubscriptionParams params = new LiClientRequestParams.LiPostSubscriptionParams(mContext, target);

Create a post client and make a request

Finally, we're ready to create the POST client and make our request using LiClientManager.getSubscriptionPostClient(LiClientRequestParams). You can read more about getSubscriptionPostClient(LiClientRequestParams) in our API reference guide and Javadoc.

Then, we make an asynchronous request.

liClient = LiClientManager.getSubscriptionPostClient(params);
liClient.processAsync(callback);

Processing the response

A successful response contains an instance of LiPostClientResponse, which contains a JSON body. It will look something like this:

{
    "status": "success",
    "message": "",
    "http_code": 200,
    "data": {
        "type": "subscription",
        "id": "0",
        "href": "/subscriptions/0",
        "target": {
            "type": "message",
            "id": "571",
            "href": "/messages/571",
            "view_href": "https://triumph.qa.lithium.com/t5/Cross-Device-Demo/A-new-question/m-p/571#M44"
        },
        "subscriber": {
            "type": "user",
            "id": "583464189",
            "href": "/users/583464189",
            "view_href": "https://triumph.qa.lithium.com/t5/user/viewprofilepage/user-id/583464189",
            "login": "Naren"
        }
    },
    "metadata": {}
}

The response returns a target (in this case, a message) and a subscriber (a user), and most important, the unique id of the subscription. You'll see how to use the value of id later when we look at how to unsubscribe from a target.

Retrieve subscriptions

To retrieve all of a user's subscriptions, we're going to follow some familiar steps.

// We create the subscription parameters to use with the request
 LiClientRequestParams liClientRequestParams = new LiClientRequestParams.LiUserSubscriptionsClientRequestParams(mContext);
// We create a GET client and make the request
LiClient subscriptionsClient = LiClientManager.getUserSubscriptionsClient(liClientRequestParams);
        subscriptionsClient.processAsync(callback...);

Processing the response

On success, the response JSON will look something like the following. You'll see items similar to the ones returned from our earlier POST example.

{
  "status" : "success",
  "message" : "",
  "http_code" : 200,
  "data" : {
    "type" : "subscriptions",
    "list_item_type" : "subscription",
    "size" : 2,
    "items" : [ {
      "type" : "subscription",
      "id" : "32",
      "href" : "/subscriptions/32",
      "target" : {
        "type" : "message",
        "id" : "568",
        "href" : "/messages/568",
        "view_href" : "/t5/abc/A-new-question/m-p/568#M271"
      },
      "subscriber" : {
        "type" : "user",
        "id" : "583464189",
        "href" : "/users/583464189",
        "view_href" : "/t5/user/viewprofilepage/user-id/583464189",
        "login" : "Naren"
      }
    }, {
      "type" : "subscription",
      "id" : "30",
      "href" : "/subscriptions/30",
      "target" : {
        "type" : "message",
        "id" : "571",
        "href" : "/messages/571",
        "view_href" : "/t5/Cross-Device-Demo/A-new-question/m-p/571#M44"
      },
      "subscriber" : {
        "type" : "user",
        "id" : "583464189",
        "href" : "/users/583464189",
        "view_href" : "/t5/user/viewprofilepage/user-id/583464189",
        "login" : "Naren"
      }
    } ]
  },
  "metadata" : { }
}

Unsubscribe from a target

In this example, we're going to unsubscribe from the post we subscribed to earlier. To unsubscribe from a post necessarily needs a subscription ID which is obtained from the subscription. Subscriptions can be synced through Getting all subscriptions or a single subscription obtained as a response to subscribe call.

  • Create a subscription delete client parameter

     String subscriptionId = "";
     LiClientRequestParams params = new LiClientRequestParams.LiDeleteSubscriptionParams(getContext(), subscriptionId);
    
  • Create a delete subscription client and process

     LiClient client = new LiClientManager.getSubscriptionDeleteClient(params);
     client.processAsync(callback);
    
  • Process the response

    On success, the response would look like this:

    {"status":"success","message":"","http_code":200,"data":{},"metadata":{}}