Skip to content

Client Usage

UsageBroker

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")
        }
})

Initialize AppUsage and its Upload Callback

 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
27
28
29
30
31
// Init EncryptionUtil API for key generation using user-provided passcode
EncryptionUtil.initialize(context);
AppUsage.initialize(context, USAGE_STORE_NAME, CpmsParameters.getSettingsParameters(),
        EncryptionUtil.getEncryptionKey(USAGE_KEY_ALIAS));

AppUsageUploader.setListener(
        new AppUsageUploader.UploadListener() {

            // Executes on UI thread
            @Override
            public void onSuccess() {
                logger.debug("AppUsage data uploaded successfully.");
            }

            // Executes on UI thread
            @Override
            public void onError(Throwable e) {
                if (e instanceof HttpException) {
                    logger.error("AppUsage upload failed. Message: {}, http code: {}",
                            ((HttpException) e).message(), ((HttpException) e).code());
                } else {
                    logger.error("AppUsage upload failed: {}", e.getMessage());
                }
            }

            // Executes on UI thread
            @Override
            public void onProgress(int percentUploaded) {
                logger.debug("AppUsage {}% uploaded.", percentUploaded);
            }
        });
 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
27
28
// Init EncryptionUtil API for key generation using user-provided passcode
EncryptionUtil.initialize(context!!)
AppUsage.initialize(context!!, USAGE_STORE_NAME, CpmsParameters.getSettingsParameters(),
        EncryptionUtil.getEncryptionKey(USAGE_KEY_ALIAS))

AppUsageUploader.setListener(
        object : AppUsageUploader.UploadListener {

            // Executes on UI thread
            override fun onSuccess() {
                logger.debug("AppUsage data uploaded successfully.")
            }

            // Executes on UI thread
            override fun onError(e: Throwable) {
                if (e is HttpException) {
                    logger.error("AppUsage upload failed. Message: {}, http code: {}",
                            e.message(), e.code())
                } else {
                    logger.error("AppUsage upload failed: {}", e.message)
                }
            }

            // Executes on UI thread
            override fun onProgress(percentUploaded: Int) {
                logger.debug("AppUsage {}% uploaded.", percentUploaded)
            }
        })

Check if AppUsage Upload is Enabled on the Server

 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
27
28
29
30
31
32
33
34
35
final Settings settings = new Settings(ClientProvider.get(),
        CpmsParameters.getSettingsParameters());

// Invoke from UI thread
settings.load(Settings.SettingTarget.APPLICATION,
        Settings.KeyPath.USAGEPOLICY,
        new Settings.CallbackListener() {

            // Executes on UI thread
            @Override
            public void onSuccess(@NonNull JSONObject settingsData) {
                try {
                    boolean valueForDataCollectionEnabled = settingsData
                            .getBoolean("dataCollectionEnabled");
                    logger.debug("AppUsage Upload enabled: {}",
                            valueForDataCollectionEnabled);
                } catch (JSONException ex) {
                    // Likely "No value for usagePolicy"
                    // which means Client Usage is not enabled for the appid
                    logger.error("Unexpected response: {}, error: {} ", settingsData, ex.getMessage());
                }
            }

            // Executes on UI thread
            @Override
            public void onError(@NonNull Throwable e) {
                // com.sap.cloud.mobile.foundation.networking.HttpException
                if (e instanceof HttpException) {
                    logger.error("Settings load failed. Message: {}, http code: {}",
                            ((HttpException) e).message(), ((HttpException) e).code());
                } else {
                    logger.error("Settings load failed: ", e.getMessage());
                }
            }
        });
 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
27
28
29
30
31
32
33
34
val settings = Settings(ClientProvider.get(),
        CpmsParameters.getSettingsParameters())

// Invoke from UI thread
settings.load(Settings.SettingTarget.APPLICATION,
        Settings.KeyPath.USAGEPOLICY,
        object : Settings.CallbackListener {

            // Executes on UI thread
            override fun onSuccess(settingsData: JSONObject) {
                try {
                    val valueForDataCollectionEnabled = settingsData
                            .getBoolean("dataCollectionEnabled")
                    logger.debug("AppUsage Upload enabled: {}",
                            valueForDataCollectionEnabled)
                } catch (ex: JSONException) {
                    // Likely "No value for usagePolicy"
                    // which means Client Usage is not enabled for the appid
                    logger.error("Unexpected response: {}, error: {} ", settingsData, ex.message)
                }

            }

            // Executes on UI thread
            override fun onError(e: Throwable) {
                // com.sap.cloud.mobile.foundation.networking.HttpException
                if (e is HttpException) {
                    logger.error("Settings load failed. Message: {}, http code: {}",
                            e.message(), e.code())
                } else {
                    logger.error("Settings load failed: ", e.message)
                }
            }
        })

Record AppUsage Data and Upload to the Server

 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
27
28
29
// Uses default targetID
AppUsage.sessionStart();//Session start is usually when app is launched or activity resumed

//Record an event with duration, unit is milliseconds (always, cannot be changed)
AppUsage.event("screens", "login", 10L,
        new AppUsageInfo().screen("welcome").action("click_ok"));
AppUsage.event("screens", "orders", 30L,
        new AppUsageInfo().screen("orders_list").action("get_orders"));

// Log an event with start and end markers, duration is calculated automatically
AppUsage.eventStart("operations", "orders",
        new AppUsageInfo().screen("create_order"));
AppUsage.eventEnd("operations", "orders",
        new AppUsageInfo().screen("create_order").value("submission_id:123"));

// Recording duration and count of an aggregate measure
AppUsage.event("views", "orders", 10L,
        new AppUsageInfo().screen("orders_page").measurement("orders_created").value("1"));

//recording an event in a misc category
AppUsage.event("views", "settings", 2L,
        new AppUsageInfo().screen("settings_page").others("settings_modified"));

// End session when app is put in background or closed
AppUsage.sessionEnd();

// Upload usage data at a later time depending on app requirements and end-user requests
// Must be invoked from UI thread
AppUsageUploader.upload(ClientProvider.get());
 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
27
28
29
// Uses default targetID
AppUsage.sessionStart()//Session start is usually when app is launched or activity resumed

//Record an event with duration, unit is milliseconds (always, cannot be changed)
AppUsage.event("screens", "login", 10L,
        AppUsageInfo().screen("welcome").action("click_ok"))
AppUsage.event("screens", "orders", 30L,
        AppUsageInfo().screen("orders_list").action("get_orders"))

// Log an event with start and end markers, duration is calculated automatically
AppUsage.eventStart("operations", "orders",
        AppUsageInfo().screen("create_order"))
AppUsage.eventEnd("operations", "orders",
        AppUsageInfo().screen("create_order").value("submission_id:123"))

// Recording duration and count of an aggregate measure
AppUsage.event("views", "orders", 10L,
        AppUsageInfo().screen("orders_page").measurement("orders_created").value("1"))

//recording an event in a misc category
AppUsage.event("views", "settings", 2L,
        AppUsageInfo().screen("settings_page").others("settings_modified"))

// End session when app is put in background or closed
AppUsage.sessionEnd()

// Upload usage data at a later time depending on app requirements and end-user requests
// Must be invoked from UI thread
AppUsageUploader.upload(ClientProvider.get())