Skip to content

Client Usage

UsageBroker

Start

try {
        UsageBroker.start(this, getApplicationContext(), "1.0", true);
    } catch (Exception ex) {
        sLogger.error(ex.getMessage());
    }
try {
        UsageBroker.start(this, getApplicationContext(), "1.0", true);
    } catch (Exception ex) {
        sLogger.error(ex.getMessage());
    }

Upload

AppUsageUploader.addUploadListener(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);
        }
});
UsageBroker.upload(getApplicationContext(), false);
AppUsageUploader.addUploadListener(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")
        }
})
UsageBroker.upload(getApplicationContext(), false)

Initialize AppUsage and Its Upload Callback

// Init EncryptionUtil API for key generation using user-provided passcode
EncryptionUtil.initialize(context);
AppUsage.initialize(context, USAGE_STORE_NAME,
        EncryptionUtil.getEncryptionKey(USAGE_KEY_ALIAS));

AppUsageUploader.addUploadListener(
        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);
            }
});
// Init EncryptionUtil API for key generation using user-provided passcode
EncryptionUtil.initialize(context!!)
AppUsage.initialize(context!!, USAGE_STORE_NAME, SettingsProvider.get(),
        EncryptionUtil.getEncryptionKey(USAGE_KEY_ALIAS))

AppUsageUploader.addUploadListener(
        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

final Settings settings = new Settings();

// 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());
                }
            }
        });
val settings = Settings()

// 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

// 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());
// 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()

Last update: April 14, 2021