Skip to content

Client Usage

The AppUsage and UsageBroker classes provided in the SAP Cloud Platform SDK for Android allow you to enable your mobile applications to collect and upload client usage data. Administrative users of the SAP Cloud Platform Mobile Services cockpit can view reports or download this data to create custom reports using the client usage data. See Usage Reporting in the mobile service documentation for more information on the server and its funtionality.

The Two Options

  1. UsageBroker - A higher level convenience helper. Simplifies initialization, collection, storage and uploading of Usage data. It can capture lifecycle events automatically. E.g.: "Session/Event start/stop"
  2. AppUsage - Work directly with the lower level objects. This option provides the ability to directly control each component, but requires greater effort in setup and maintenance

    ** NOTE: Only 1 usage provider should be used at a time.

UsageBroker

Easily collect, store and upload client usage event data. The steps to use it:

  1. Initialize the broker. We suggest adding this call to the application's onCreate().
  2. Start the broker. Add this call at the earliest opportunity (after collecting the server settings)
  3. Call Upload (anywhere and often). It will only upload on the requested frequency.
Initialize
1
2
// In your Application class, init the UsageBroker
UsageBroker.initialize(this, true);
1
2
// In your Application class, init the UsageBroker
UsageBroker.initialize(this, true)
Start
1
2
3
4
5
try {
        UsageBroker.start(getApplicationContext(), AppState.getInstance().getSettingsParameters());
    } catch (Exception ex) {
        sLogger.error(ex.getMessage());
    }
1
2
3
4
5
try {
        UsageBroker.start(getApplicationContext(), AppState.getInstance().getSettingsParameters())
    } catch (Exception ex) {
        sLogger.error(ex.getMessage())
    }
Upload
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
UsageBroker.upload(false, new AppUsageUploader.UploadListener() {
        @Override
        public void onSuccess() {
                sLogger.debug("Usage upload complete, time taken (in nanos): " + (System.nanoTime() - startTime));
        }

        @Override
        public void onError(Throwable error) {
                Toast.makeText(getActivity(), "Upload Err:\n"+error.getMessage(), Toast.LENGTH_LONG).show();
                if (error instanceof HttpException) {
                        sLogger.debug("Upload server error: {}, code = {}",
                                ((HttpException) error).message(), ((HttpException) error).code());
                } else {
                        sLogger.debug("Upload error: {}", error.getMessage());
                }
        }

        @Override
        public void onProgress(int i) {
                sLogger.debug("Usage upload progress: " + i);
        }
});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
UsageBroker.upload(false, object : AppUsageUploader.UploadListener {
        override fun onSuccess() {
                sLogger.debug("Usage upload complete, time taken (in nanos): " + (System.nanoTime() - startTime))
        }

        override fun onError(error: Throwable) {
                Toast.makeText(activity, "Upload Err:\n" + error.message, Toast.LENGTH_LONG).show()
                if (error is HttpException) {
                    sLogger.debug("Upload server error: {}, code = {}",
                            error.message(), error.code())
                } else {
                    sLogger.debug("Upload error: {}", error.message)
                }
        }

        override fun onProgress(i: Int) {
                sLogger.debug("Usage upload progress: $i")
        }
})

Sessions

For the purposes of reporting, define a user session as the duration the mobile application is in the foreground. The session acts as a container for event metrics data. In addition, it contains information such as the:

  • Device Platform (Android/IOS)
  • Device Platform version
  • Device Id
  • Application Id
  • Application Version

Event Metrics Data

An application can report any event metrics data using AppUsageInfo. SAP Cloud Platform Mobile Services supports a standard schema to collect event metrics. The values for the metrics and how to interpret them for a custom report is up to your mobile application designers and product managers.

The "AppUsageInfo" class consists fo the following fields and can collect metrics for the following events:

Field Description
Type The event type
Key The key to identify the event
Action The action associated with the event
Behaviour User-defined behavior properties of the event
Category User-defined event category type
Duration The duration of the event in milli-seconds
Element The SDK/UI element associated with the event
Measurement User-defined measurement of the event, e.g., UI element size
Others Any other user-defined properties associated with the event
Result User-defined result associated with the event, usually used with 'Action'
Screen The properties of the screen
Case User-defined case
Unit The unit associated with 'Measurement'
Value User-defined value properties
View Android View related properties

Reporting

During the reporting phase, client data is collected and persisted in an encrypted store on the device. The data can then be uploaded to the SAP Cloud Platform and viewed in client usage reports. See the uploading section in this topic for more information.

Reporting involves:

  1. Initializing the AppUsage class
  2. Recording session start
  3. Reporting event metrics
  4. Recording session end

Initializing AppUsage

A one-time initialization is required. An encryption key is required to encrypt the underlying persistence store.

SAP recommends that you use the encryption utility to obtain the encryption key. If it is the first time AppUsage is being configured and null is provided as the encryption key, a key is generated transparently and is used for subsequent configure calls. See Encryption utility for more information.

This must happen before any AppUsage related calls are done.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Application Id and version in SettingsParameter will be used during reporting and uploading to form Mobile Service URL.
// Encryption key is used to encrypt the underlying persistence store.
SettingsParameters settingsParameters = null;

try {
    settingsParameters = new SettingsParameters(
            "https://mobilepreview-yourAccount.hana.ondemand.com/",// CPMS server base URL
            "appId",   // CPMS app ID
            "deviceId",// This device's ID
            "1.0");    // CPMS app version
} catch (MalformedURLException ex) {
    // If serverBaseUrl is malformed.
}

byte[] encrytionKey = EncryptionUtil.getEncryptionKey("aliasForAppUsage", passcodeFromUser);

try {
    AppUsage.initialize(appContext, "myUsageStore", settingsParameters, encrytionKey);

    // Or passes null and the AppUsage will generate an encryption key to encrypt the persistence store
    // and subsequent 'initialize' calls.
    //      AppUsage.initialize(appContext, "myUsageStore", settingsParameters, null);
} catch (OpenFailureException ex) {
    logger.error("Failed to open Usage store.", ex);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Application Id and version in SettingsParameter will be used during reporting and uploading to form Mobile Service URL.
// Encryption key is used to encrypt the underlying persistence store.
var settingsParameters: SettingsParameters? = null

try {
    settingsParameters = SettingsParameters(
            "https://mobilepreview-yourAccount.hana.ondemand.com/", // CPMS server base URL
            "appId", // CPMS app ID
            "deviceId", // This device's ID
            "1.0")    // CPMS app version
} catch (ex: MalformedURLException) {
    // If serverBaseUrl is malformed.
}

val encrytionKey = EncryptionUtil.getEncryptionKey("aliasForAppUsage", passcodeFromUser)

try {
    AppUsage.initialize(appContext!!, "myUsageStore", settingsParameters!!, encrytionKey)

    // Or passes null and the AppUsage will generate an encryption key to encrypt the persistence store
    // and subsequent 'initialize' calls.
    //      AppUsage.initialize(appContext, "myUsageStore", settingsParameters, null);
} catch (ex: OpenFailureException) {
    logger.error("Failed to open Usage store.", ex)
}

Recording the Session Start

Reporting must begin with a sessionStart and end with a sessionEnd. Any calls to event reporting without a sessionStart will be ignored. Event metrics reporting using eventStart, eventEnd and event must happen after calling sessionStart and before sessionEnd is called.

A call to sessionStart marks the start of a session with the session related attributes such as Platform and Platform Version. Consecutive calls to sessionStart without calling sessionEnd ends the current session and creates a new session.

1
AppUsage.sessionStart();
1
AppUsage.sessionStart()

Reporting Event Metrics

After a sessionStart is called, one or more event records can be reported. Events can be reported using single call to event() or a pair of eventStart() and eventEnd() calls. In the single call, your application is responsible to provide duration information if applicable. In the paired call, the event duration is automatically calculated.

A string value is accepted for each of the event metrics field. It is up to you to decide what value should be recorded in each of the fields.

1
2
3
AppUsage.eventStart("filterEventType", "productFilter",
        new AppUsageInfo()
                .screen("Product Filter"));  // Uses one or more of the event metrics methods-- screen, element, view, category, etc.
1
2
3
AppUsage.eventStart("filterEventType", "productFilter",
        AppUsageInfo()
                .screen("Product Filter"))  // Uses one or more of the event metrics methods-- screen, element, view, category, etc.
1
2
3
AppUsage.eventEnd("filterEventType", "productFilter",
    new AppUsageInfo()
        .screen("Product Filter"));
1
2
3
AppUsage.eventEnd("filterEventType", "productFilter",
        AppUsageInfo()
                .screen("Product Filter"))
1
2
3
4
5
6
7
8
9
// Single event call.
AppUsage.event(
    "eventType1",          // Event type, optional.
    "testEvent1Key",       // Event key. When not specified, 'other' will be used.
    4L,                    // Duration.
    new AppUsageInfo()     // Event metrics using AppUsageInfo.
           .screen("firstScreen")
           .value("randomValue")
           .category("category1");
1
2
3
4
5
6
7
8
9
// Single event call.
AppUsage.event(
        "eventType1", // Event type, optional.
        "testEvent1Key", // Event key. When not specified, 'other' will be used.
        4L, // Duration.
        AppUsageInfo()     // Event metrics using AppUsageInfo.
                .screen("firstScreen")
                .value("randomValue")
                .category("category1"))

Recording the Session End

A call to sessionEnd marks the end of a session.

1
AppUsage.sessionEnd();
1
AppUsage.sessionEnd()

Uploading

Before using AppUsageUploader, enable the mobile service to upload application-specific usage statistics and reports from mobile devices. See Defining Usage Report Policy.

AppUsageUploader retrieves the usage data reported before a cut-off date from the underlying persistence store, converts them to the format required by the mobile service, and then uploads them.

Registering the Upload Listener

To be notified that the upload is successful or failed, or to get upload progress, implement AppUsageUploader.UploadListener. This is an optional but recommended step. Note that all callback methods are invoked in UI(main) thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// All callback methods will be invoked in UI(main) thread.
class MyUploadListener implements AppUsageUploader.UploadListener {
    @Override
    public void onSuccess() {
        logger.debug("Usage Upload completed successfully");

        // For example, put a toast message.
    }

    @Override
    public void onError(Throwable error) {
        if (error instanceof HttpException) {
            logger.debug("Usage Upload server error: {}, code = {}", ((HttpException) error).getMessage(),
                    ((HttpException) error).getCause());
        } else {
            logger.debug("Usage Upload error: {}", error.getMessage());
        }
    }

    @Override
    public void onProgress(int percentage) {
        // For example, updates the progress dialog/bar.
    }
}

MyUploadListener myUploadListener = new MyUploadListener();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
internal var myUploadListener = MyUploadListener()

// All callback methods will be invoked in UI(main) thread.
internal inner class MyUploadListener : AppUsageUploader.UploadListener {
    override fun onSuccess() {
        logger.debug("Usage Upload completed successfully")

        // For example, put a toast message.
    }

    override fun onError(error: Throwable) {
        if (error is HttpException) {
            logger.debug("Usage Upload server error: {}, code = {}", error.message,
                    error.cause)
        } else {
            logger.debug("Usage Upload error: {}", error.message)
        }
    }

    override fun onProgress(percentage: Int) {
        // For example, updates the progress dialog/bar.
    }
}

Set the listener by calling:

1
AppUsageUploader.setListener(myUploadListener);
1
AppUsageUploader.setListener(myUploadListener)

Starting the Upload

To start the upload, call upload from the UI(main) thread. All usage data retrieval and uploading is performed in an AsyncTask.

Note

Make sure the mobile application has already authenticated with the server before the upload call. This call requires authentication.

1
AppUsageUploader.upload(okHttpClient); // okHttpClient was used for server authentication.
1
AppUsageUploader.upload(ClientProvider.get()) // okHttpClient was used for server authentication.

Viewing Usage Reports on the Server

After successful client data upload, you can view the data from the SAP Cloud Platform Mobile Services cockpit. See Viewing Client Data Report.