DEVELOPERS BLOG

Integrate BEMS Presence Service into Your Application

CODE SAMPLES / 07.12.17 / Mark Sohm

Previous blog posts explained how to use the BEMS Docs service and BEMS Directory service.  Today we look at another BlackBerry Enterprise Mobility Server (BEMS) service, the Presence Service.

BEMS Presence Lookup Service Development Resources

The presence service allows you to query for and subscribe to changes made to user’s Microsoft Lync presence status.  Like the services in the previous blog posts, the BEMS Presence service also has a REST interface.  Where it differs is that it makes use of BlackBerry Dynamics push notifications to alert when a user in a subscription changes.  You can provide a list of users to subscribe to, and then receive updates when any of those users change their status.

The subscription mechanism makes use of a push and pull model.  The application will receive a push message with a unique key when there are updates.  It can send that notification key to the BEMS Presence service, which will return the updated users and their statuses.

To keep the subscription active, the application needs to ping the presence service before it’s configured timeout.  The default timeout is 3 minutes, but it can be changed by your administrator.

Let’s look at how the Android sample BEMSPresenceSample makes use of this service.  If you have read the previous blog articles on using the BEMS Docs or Directory services, you’ll notice that the code for service discovery is re-used from those samples.

The BEMSPresenceSample has two similar activities, PresenceActivtyRich and PresenceActivityRaw.  The both have similar functionality except that PresenceActivityRich displays the results in a formatted ListView while PresenceActivityRaw displays the raw JSON that is sent and received.

Preparing for Push

To support push subscription updates, the sample needs to create a BlackBerry Dynamics Push channel.  That process is started in GDStateListener.onAuthorized() within PresenceActivityRich and PresenceActivityRaw where the registerReceiver() and setupPushChannel() methods are called.

registerReceiver() is used to create a receiver to listen for the broadcast intent when the push connection status is changed.  That way, if push isn’t initially available, the push channel can be created once it is.

private void registerReceiver()
{
    if (receiver == null)
    {
        receiver = new BroadcastReceiver()
        {
            @Override
            public void onReceive(Context context, Intent intent)
            {
                logOutput("Received GD_CONNECTIVITY_ACTION intent.");
                setupPushChannel();
            }
        };

        GDAndroid.getInstance().registerReceiver(receiver,
                new IntentFilter(GDConnectivityManager.GD_CONNECTIVITY_ACTION));
    }
}

setupPushChannel() is where the push channel is created if the push service is available.

private void setupPushChannel()
{
    logOutput("Setup Push Channel.");

    GDNetworkInfo networkInfo =
GDConnectivityManager.getActiveNetworkInfo();
    logOutput("isPushChannelAvailable = " +
     networkInfo.isPushChannelAvailable());

    if (pushChannel == null && networkInfo.isPushChannelAvailable())
    {
        pushChannel = new PushChannel();
        pushChannel.setListener(this);
        pushChannel.connect();

        logOutput("Push Channel Created.");
    }
}

The application also implements the PushChannelListener interface, which has methods to inform when the push channel has opened (onChannelOpen(String pushToken), closed (onChannelClose(String token)) and when a push message arrives (onChannelMessage(String message)).  In the onChannelOpen(String pushToken) method the sample saves the pushToken for use in a header when making a subscription request.  The BEMS Presence Service uses this token when it sends a push.

@Override
public void onChannelOpen(String token)
{
    pushToken = token;
}

@Override
public void onChannelMessage(String message)
{
    logOutput("Update received via push:");
    logOutput(message);

    //Trigger a contact update poll.
    getContactUpdates(true);
}

@Override
public void onChannelClose(String token)
{
    logOutput("Push Channel Connection Closed.");
    pushToken = null;
}

Discovering the Presence Service

BEMS services are discoverable by BlackBerry Dynamics applications using BlackBerry Dynamics service discovery.  This isn’t specific to BEMS, but is a method any local or remote service can use to advertise itself.  UEM administrators have the capability to enable and disable these services for their users.  The first few steps use service discovery to determine if the user’s BlackBerry Dynamics environment has an active BEMS Presence service that they are entitled to use.  We query for this using the getServiceProvidersFor method.

Vector<GDServiceProvider> providers =
        GDAndroid.getInstance().getServiceProvidersFor(
            "com.good.gdservice.enterprise.directory",
            "1.0.0.0", GDServiceProviderType.GDSERVICEPROVIDERSERVER);

This call returns a Vector containing GDServiceProvider.  From that Vector, we can filter the services that support the BEMS Presence service and get their server name, port and priority.  Priority can be used to choose from a pool of BEMS servers and is configured by the UEM administrator.  The parseServiceDetails method in the MainActivity class of the sample extracts and stores that information.

Constructing the Headers

BEMS identifies and authenticates the user using a BlackBerry Dynamics Authentication Token.  The application requests a token using the destination BEMS server address.  When the BEMS server receives the requests, it connects to the BlackBerry Control server to verify the token is valid.  The token is requested using the GDUtility.getGDAuthToken(final String challenge, final String serverName, final GDAuthTokenCallback callback) method.  The sample application makes this request in its onGetAuthToken method of PresenceActivityRich and PresenceActivityRaw classes.

The BD Authentication Token is received by the application in the onGDAuthTokenSuccess callback method of the PresenceActivityRich and PresenceActivityRaw classes in the sample app.  Now that it has the token, the app can add it to the HTTP requests made to the BEMS servers as a header like this:

ArrayList<BasicHeader> headers = new ArrayList<>();
headers.add(new BasicHeader("X-Good-GD-AuthToken", gdAuthToken));

A device identifier is required by the BEMS Presence service to assist it with subscription management.

TelephonyManager telManager =
(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
headers.add(new BasicHeader("X-Good-DeviceId",
     telManager.getDeviceId()));

Optionally, if the BlackBerry Dynamics Push service is available the push token is added as a header.

if (pushToken != null)
{
    headers.add(new BasicHeader("X-Good-GNP-Token", pushToken));
}

Finally, the following headers are added to describe the content we are sending (JSON) and type of content we expect back.

headers.add(new BasicHeader("Content-Type", "application/json"));
headers.add(new BasicHeader("Accept", "application/json"));

Response and Error Codes

The following HTTP response code are used by all REST calls of the BEMS Presence service.

200 – OK, the request was successful.

404 – BEMS Presence service is not installed.

500 – Internal Server Error with error JSON object in the response payload.  Error code 1102 means presence service is up, and either the Microsoft Lync presence provider service is not up or Lync presence provider service is up, but presence service is not configured correctly to reach it.

501 – BEMS Presence Service is not set up.

503 – BEMS Presence Service is online, but the Microsoft Lync presence service is not running.

Creating a Presence Subscription

A subscription is created by sending a notification key and list of contact email addresses.  The presence service will maintain the client’s subscription contact list for a configured time frame.  The notification key is a value that is unique for the client application and must be re-used when requesting subscription updates or deleting the subscription.  The subscription request is made by sending a POST request, initiated in the onSubscribe(View view) method in PresenceActivityRich and PresenceActivityRaw.

Subscribe

POST /presence/subscriptions
{
    "notify" : "notificationKey",  // should be unique on client
    "contacts" : [ <listOfContacts> ]
}

notify – An alphanumeric value without spaces or colons that uniquely identifies the subscription.  This is sent in all requests and returned with subscription requests.

contacts – An array of contacts, specified as email addresses.

The BEMS Presence Service will return JSON after a successful subscription request with the JSON below.

 

{
         "target": <notification key>,
         "sequence" : <sequence number >,
         "expiry": <seconds until the subscriptions expire>,
         "contacts":
         [
             {
            "id": <userId>,
                "sipaddress": <user's sip address>,
                "presence": <presence, for development/debug purpose, client should not rely on it for display purpose>,
                "secondarypresence" : <secondary presence>,
                "availability": <presence number>,
                "message": <personal message>,
                "outofoffice": <out of office message>,
                "error": <error message> (contact level error, e.g. "unknown contact")
             },
             {
                "id": <userId>,
                "sipaddress": <user's sip address>,
                "presence": <presence, for development/debug purpose, client should not rely on it for display purpose>,
                "secondarypresence" : <secondary presence>,
                "availability": <presence number>,
                "message": <personal message>,
                "outofoffice": <out of office message>,
                "error": <error message> (contact level error, e.g. "unknown contact")
             }
       ] ,
    "error": (service level error, if there's error here, other data above won't be included)
        {
            "errorCode": <error code>,
            "message": <error message>
        }
}

 

target – This is the notification key that was sent in the subscription request.

sequence – A 64-bit signed integer that the application must include it in its next polling request.

expiry – Approximate number of seconds until the subscription expires.  -1 if this is the final notification.

error – Error message from the BEMS Presence service.  If there is an error here, the data above won’t be included.

Handling Subscription Updates

When a change in a contact’s status is detected by the BEMS Presence service, it sends a push to alert the application that an update is available.  This is received in the onChannelMessage(String message) method of PresenceActivityRich and PresenceActivityRaw and triggers a call to getContactUpdates(boolean isPushTriggered), which makes a GET request to retrieve the updates.  Note that only updated contacts are returned, not the full list subscribed to.

Get Updates for Subscribed Contacts Whose Presence Status Changed

GET /presence/subscriptions/{notify}?sequence=<sequence number>

notify – An alphanumeric value without spaces or colons that uniquely identifies the subscription.  This is sent in all requests and returned with subscription requests.

sequence – The sequence value from the previously received JSON.

To get an update for all contacts, not just those that were changed since the last update, make the same request but without the sequence number.

Get a Snapshot of Data for All Subscribed Contacts

GET /presence/subscriptions/{notify}

The JSON format of the response from these requests mirror what is returned from the original subscription request, which was shown above in the “Creating a Presence Subscription” section.

Unsubscribing from a Presence Subscription

Subscriptions that are no longer required can be deleted.  Alternatively, your application can take no action and what for the subscription timeout to occur.  In the sample, the subscription request is made in the onUnSubscribe(View view) method in the PresenceActivityRich and PresenceActivityRaw classes.  Perform an delete subscription request be sending an HTTP delete with the subscription’s notify key.

Delete Subscription

DELETE /presence/subscriptions/<notifyKey>

This request does not return any JSON.

Wrapping Up

I hope this blog posts help you get started with integrating the BEMS Presence Service into your application.  If you have any questions, head over to our BlackBerry Dynamics developer forums for help.

For more developer resources or to get started on any of our platforms, please visit the BlackBerry Developer Community website.

 

Mark Sohm

About Mark Sohm

Senior Technical Solutions Manager on the Solution Architects team.

Mark Sohm joined BlackBerry in 2003 and currently works as a Senior Technical Solutions Manager on the Solutions Architects team. Mark Sohm has been helping developers create applications using BlackBerry technologies for over 15 years, starting way back with the very first BlackBerry JDK on BlackBerry OS 3.6 through to BlackBerry 10 and now Android with BlackBerry Dynamics and Android Enterprise.