Back to top

Tutorial - Upgrade to Knox Workspace

Last updated April 25th, 2024

The following instructions describe how upgrade your Android P.O to a premium Knox Workspace.

Upgrade path

Upgrading from Android P.O to a Knox Workspace is easy. All you need to do is activate a Knox License, and your profile automatically updates. You activate a Knox license in 4 steps:

  1. Get a Knox License
  2. Create the license receiver class
  3. Register the license receiver class
  4. Call the Activate license API

Knox Platform for Enterprise (KPE) license key

Before you can use the in your app, you need to obtain a Knox Platform for Enterprise (KPE) license key.

Why do you need a license? Samsung Knox uses a license manager server to identify and authenticate apps that can take control of devices. You use your KPE key in your app for authentication purposes. You KPE key is passed to every device that you manage with your app. Should your KPE key become compromised, Samsung can revoke it, and any app that uses the compromised key can’t take control of a device.

For the purpose of this tutorial, we are using the KPE key because we are calling the free restriction policy setCameraState.

Get an KPE license

If you don’t have access to License keys in the Knox Developer Portal, please contact your Samsung sales partner to request access.

  1. Request a license from the Knox Developer portal.

  2. Select a Development key type, which you can use during pre-production on a limited number of devices for a limited time period.

    Later, when you are ready to commercialize your app, select a Commercial key if you are using Standard permissions. If you are using Premium or Customization permissions, until later this year you need to purchase ELM and KLM keys from a Knox Reseller.

  3. Enter a key alias, for example, MDMKEY.

  4. For added security, you can identify the app that will use this license; only this app will be allowed to activate this license. During development however, you can skip this step considering your app is not yet ready.

  5. Click GENERATE LICENSE KEY. The Not for Resale Agreement appears.

  6. If your app needs to run on devices with Knox 2.7 or lower, you also need to scroll down to the bottom of this page to generate a backwards-compatible key. Note that this key only needs to be generated once and can be used with all of your KPE keys.

  7. After you agree to the terms, the Your New License Keys page displays your keys. Keep them secure.

In your app, create a new class called SampleLicenseReceiver.java. This contains a license receiver for your KPE key, as well as a license receiver for your backwards-compatible key if you are using one.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.samsung.android.knox.license.EnterpriseLicenseManager;
import com.samsung.android.knox.license.KnoxEnterpriseLicenseManager;


public class SampleLicenseReceiver extends BroadcastReceiver {

    private int DEFAULT_ERROR_CODE = -1;

    private void showToast(Context context, int msg_res) {
        Toast.makeText(context, context.getResources().getString(msg_res), Toast.LENGTH_SHORT).show();
    }

    private void showToast(Context context, String msg) {
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        int msg_res = -1;

        if (intent == null) {
            // No intent action is available
            showToast(context, R.string.no_intent);
            return;
        } else {
            String action = intent.getAction();
            if (action == null) {
                // No intent action is available
                showToast(context, R.string.no_intent_action);
                return;
            }  else if (action.equals(KnoxEnterpriseLicenseManager.ACTION_LICENSE_STATUS)) {
                // KPE activation result Intent is obtained
                int errorCode = intent.getIntExtra(KnoxEnterpriseLicenseManager.EXTRA_LICENSE_ERROR_CODE, DEFAULT_ERROR_CODE);

                if (errorCode == KnoxEnterpriseLicenseManager.ERROR_NONE) {
                    // KPE activated successfully
                    showToast(context, R.string.klm_activated_successfully);
                    Log.d("SampleLicenseReceiver", context.getString(R.string.klm_activated_successfully));
                    return;
                } else {
                    // KPE activation failed
                    switch (errorCode) {
                        case KnoxEnterpriseLicenseManager.ERROR_INTERNAL:
                            msg_res = R.string.err_klm_internal;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_INTERNAL_SERVER:
                            msg_res = R.string.err_klm_internal_server;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_INVALID_LICENSE:
                            msg_res = R.string.err_klm_license_invalid_license;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_INVALID_PACKAGE_NAME:
                            msg_res = R.string.err_klm_invalid_package_name;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_LICENSE_TERMINATED:
                            msg_res = R.string.err_klm_license_terminated;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_NETWORK_DISCONNECTED:
                            msg_res = R.string.err_klm_network_disconnected;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_NETWORK_GENERAL:
                            msg_res = R.string.err_klm_network_general;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_NOT_CURRENT_DATE:
                            msg_res = R.string.err_klm_not_current_date;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_NULL_PARAMS:
                            msg_res = R.string.err_klm_null_params;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_UNKNOWN:
                            msg_res = R.string.err_klm_unknown;
                            break;
                        case KnoxEnterpriseLicenseManager.ERROR_USER_DISAGREES_LICENSE_AGREEMENT:
                            msg_res = R.string.err_klm_user_disagrees_license_agreement;
                            break;
                        default:
                            // Unknown error code
                            String errorStatus = intent.getStringExtra(KnoxEnterpriseLicenseManager.EXTRA_LICENSE_STATUS);
                            String msg = context.getResources().getString(R.string.err_klm_code_unknown, Integer.toString(errorCode), errorStatus);
                            showToast(context, msg);
                            Log.d("SampleLicenseReceiver", msg);
                            return;
                    }

                    // Display KPE error message
                    showToast(context, msg_res);
                    Log.d("SampleLicenseReceiver", context.getString(msg_res));
                    return;
                }
            }
           /* The code block below is only required if you are using a backwards-compatible key. */
           else if (action.equals(EnterpriseLicenseManager.ACTION_LICENSE_STATUS)) {
                // Backwards-compatible key activation result Intent is obtained
                int errorCode = intent.getIntExtra(EnterpriseLicenseManager.EXTRA_LICENSE_ERROR_CODE, DEFAULT_ERROR_CODE);

                if (errorCode == EnterpriseLicenseManager.ERROR_NONE) {
                    // Backwards-compatible key  activated successfully
                    showToast(context, R.string.elm_activated_succesfully);
                    Log.d("SampleLicenseReceiver", context.getString(R.string.elm_activated_succesfully));
                    return;
                } else {
                    // Backwards-compatible key  activation failed
                    switch (errorCode) {
                        case EnterpriseLicenseManager.ERROR_INTERNAL:
                            msg_res = R.string.err_elm_internal;
                            break;
                        case EnterpriseLicenseManager.ERROR_INTERNAL_SERVER:
                            msg_res = R.string.err_elm_internal_server;
                            break;
                        case EnterpriseLicenseManager.ERROR_INVALID_LICENSE:
                            msg_res = R.string.err_elm_license_invalid_license;
                            break;
                        case EnterpriseLicenseManager.ERROR_INVALID_PACKAGE_NAME:
                            msg_res = R.string.err_elm_invalid_package_name;
                            break;
                        case EnterpriseLicenseManager.ERROR_LICENSE_TERMINATED:
                            msg_res = R.string.err_elm_license_terminated;
                            break;
                        case EnterpriseLicenseManager.ERROR_NETWORK_DISCONNECTED:
                            msg_res = R.string.err_elm_network_disconnected;
                            break;
                        case EnterpriseLicenseManager.ERROR_NETWORK_GENERAL:
                            msg_res = R.string.err_elm_network_general;
                            break;
                        case EnterpriseLicenseManager.ERROR_NOT_CURRENT_DATE:
                            msg_res = R.string.err_elm_not_current_date;
                            break;
                        case EnterpriseLicenseManager.ERROR_NULL_PARAMS:
                            msg_res = R.string.err_elm_null_params;
                            break;
                        case EnterpriseLicenseManager.ERROR_SIGNATURE_MISMATCH:
                            msg_res = R.string.err_elm_sig_mismatch;
                            break;
                        case EnterpriseLicenseManager.ERROR_UNKNOWN:
                            msg_res = R.string.err_elm_unknown;
                            break;
                        case EnterpriseLicenseManager.ERROR_USER_DISAGREES_LICENSE_AGREEMENT:
                            msg_res = R.string.err_elm_user_disagrees_license_agreement;
                            break;
                        case EnterpriseLicenseManager.ERROR_VERSION_CODE_MISMATCH:
                            msg_res = R.string.err_elm_ver_code_mismatch;
                            break;
                        default:
                            // Unknown error code
                            String errorStatus = intent.getStringExtra(EnterpriseLicenseManager.EXTRA_LICENSE_STATUS);
                            String msg = context.getResources().getString(R.string.err_elm_code_unknown, Integer.toString(errorCode), errorStatus);
                            showToast(context, msg);
                            Log.d("SampleLicenseReceiver", msg);
                            return;
                    }

                    // Display Backwards-compatible key error message
                    showToast(context, msg_res);
                    Log.d("SampleLicenseReceiver", context.getString(msg_res));
                    return;
                }
            }
        }
    }
}
        

Register the License Receiver class

When the KPE license is validated, the com.samsung.android.knox.intent.action.LICENSE_STATUS intent is emitted. The app uses the SampleLicenseReceiver class to intercept this intent.

Paste this code in AndroidManifest.xml to define the receiver for com.samsung.android.knox.intent.action.LICENSE_STATUS intents:

 <receiver android:name=".SampleLicenseReceiver" >
	<intent-filter>
	<action android:name="com.samsung.android.knox.intent.action.LICENSE_STATUS" />
	</intent-filter>
</receiver>

When your app receives a com.samsung.android.knox.intent.action.LICENSE_STATUS intent, it passes the intent SampleLicenseReceiver.onReceive(). This method is where you can have your app respond to the license being activated.

Activate the license

Use this method in your MainActivity to activate the license.

private void activateKPELicense() {
    // Instantiate the KnoxEnterpriseLicenseManager class to use the activateLicense method
    KnoxEnterpriseLicenseManager KPEManager = KnoxEnterpriseLicenseManager.getInstance(this);

    try {
        // KPE License Activation TODO Add KPE license key to Constants.java
        KPEManager.activateLicense(Constants.KPE_LICENSE_KEY);
        mUtils.log(getResources().getString(R.string.klm_license_progress));

    } catch (Exception e) {
        mUtils.processException(e, TAG);
    }
}

/* The code block below is only required if you are using a backwards-compatible key. */
private void activateBackwardsCompatibleKey() {
    // Instantiate the EnterpriseLicenseManager class to use the activateLicense method
    EnterpriseLicenseManager BackwardsCompatibleKeyManager = EnterpriseLicenseManager.getInstance(this);

    try {
        // Backwards-Compatible Key Activation TODO Add license key to Constants.java
        elmManager.activateLicense(Constants.ELM_LICENSE_KEY);
        mUtils.log(getResources().getString(R.string.license_progress));

    } catch (Exception e) {
        mUtils.processException(e, TAG);
    }
}
        

When you launch the app for the first time and activate the license, you will see a Samsung confirmation dialog. This only appears once per license activation. Agree to the terms and conditions and tap CONFIRM.

KLMS agent

Tutorial progress

You’ve completed 5/7 steps!

Next

Is this page helpful?