Activate a license
Last updated September 26th, 2024
Your app activates your Knox license to authenticate API access. For more information, see Knox licenses.
To activate your Knox license, you must have Knox 2.4 or higher. The code sample below describes a common method applicable to all devices with Knox 2.4 or higher.
However, if your solution is only for devices with Knox 3.8 or higher, follow the license activation method under the Knox 3.8 or higher versions only tab, as that code provides better performance compared to the generic code.
On this tab
Create the License Receiver class
In your app, create a new class called SampleLicenseReceiver.java
, which contains a license receiver for your KPE and backwards compatible keys.
package com.samsung.knox.example.gettingstarted;
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.KnoxEnterpriseLicenseManager;
import com.samsung.android.knox.license.EnterpriseLicenseManager;
public class SampleLicenseReceiver extends BroadcastReceiver {
private static final int DEFAULT_ERROR_CODE = -1;
private void showToast(Context context, String msg) {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null) {
// No intent action is available
showToast(context, context.getResources().getString(R.string.no_intent));
} else {
String action = intent.getAction();
if (action == null) {
// No intent action is available
showToast(context, context.getResources().getString(R.string.no_intent_action));
} 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, context.getResources().getString(R.string.kpe_activated_succesfully));
Log.d("SampleLicenseReceiver", context.getString(R.string.kpe_activated_succesfully));
} else {
// KPE activation failed
// Display KPE error message
String errorMessage = getKPEErrorMessage(context, intent, errorCode);
showToast(context, errorMessage);
Log.d("SampleLicenseReceiver", errorMessage);
}
} 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, context.getResources().getString(R.string.elm_action_successful));
Log.d("SampleLicenseReceiver", context.getString(R.string.elm_action_successful));
} else {
// Backwards compatible key activation failed
// Display backwards compatible key error message
String errorMessage = getELMErrorMessage(context, intent, errorCode);
showToast(context, errorMessage);
Log.d("SampleLicenseReceiver", errorMessage);
}
}
}
}
private String getELMErrorMessage(Context context, Intent intent, int errorCode) {
String message;
switch (errorCode) {
case EnterpriseLicenseManager.ERROR_INTERNAL:
message = context.getResources().getString(R.string.err_elm_internal);
break;
case EnterpriseLicenseManager.ERROR_INTERNAL_SERVER:
message = context.getResources().getString(R.string.err_elm_internal_server);
break;
case EnterpriseLicenseManager.ERROR_INVALID_LICENSE:
message = context.getResources().getString(R.string.err_elm_licence_invalid_license);
break;
case EnterpriseLicenseManager.ERROR_INVALID_PACKAGE_NAME:
message = context.getResources().getString(R.string.err_elm_invalid_package_name);
break;
case EnterpriseLicenseManager.ERROR_LICENSE_TERMINATED:
message = context.getResources().getString(R.string.err_elm_licence_terminated);
break;
case EnterpriseLicenseManager.ERROR_NETWORK_DISCONNECTED:
message = context.getResources().getString(R.string.err_elm_network_disconnected);
break;
case EnterpriseLicenseManager.ERROR_NETWORK_GENERAL:
message = context.getResources().getString(R.string.err_elm_network_general);
break;
case EnterpriseLicenseManager.ERROR_NOT_CURRENT_DATE:
message = context.getResources().getString(R.string.err_elm_not_current_date);
break;
case EnterpriseLicenseManager.ERROR_NULL_PARAMS:
message = context.getResources().getString(R.string.err_elm_null_params);
break;
case EnterpriseLicenseManager.ERROR_SIGNATURE_MISMATCH:
message = context.getResources().getString(R.string.err_elm_sig_mismatch);
break;
case EnterpriseLicenseManager.ERROR_UNKNOWN:
message = context.getResources().getString(R.string.err_elm_unknown);
break;
case EnterpriseLicenseManager.ERROR_USER_DISAGREES_LICENSE_AGREEMENT:
message = context.getResources().getString(R.string.err_elm_user_disagrees_license_agreement);
break;
case EnterpriseLicenseManager.ERROR_VERSION_CODE_MISMATCH:
message = context.getResources().getString(R.string.err_elm_ver_code_mismatch);
break;
default:
// Unknown error code
String errorStatus = intent.getStringExtra(
EnterpriseLicenseManager.EXTRA_LICENSE_STATUS);
message = context.getResources()
.getString(R.string.err_elm_code_unknown, Integer.toString(errorCode), errorStatus);
}
return message;
}
private String getKPEErrorMessage(Context context, Intent intent, int errorCode) {
String message;
switch (errorCode) {
case KnoxEnterpriseLicenseManager.ERROR_INTERNAL:
message = context.getResources().getString(R.string.err_kpe_internal);
break;
case KnoxEnterpriseLicenseManager.ERROR_INTERNAL_SERVER:
message = context.getResources().getString(R.string.err_kpe_internal_server);
break;
case KnoxEnterpriseLicenseManager.ERROR_INVALID_LICENSE:
message = context.getResources().getString(R.string.err_kpe_licence_invalid_license);
break;
case KnoxEnterpriseLicenseManager.ERROR_INVALID_PACKAGE_NAME:
message = context.getResources().getString(R.string.err_kpe_invalid_package_name);
break;
case KnoxEnterpriseLicenseManager.ERROR_LICENSE_TERMINATED:
message = context.getResources().getString(R.string.err_kpe_licence_terminated);
break;
case KnoxEnterpriseLicenseManager.ERROR_NETWORK_DISCONNECTED:
message = context.getResources().getString(R.string.err_kpe_network_disconnected);
break;
case KnoxEnterpriseLicenseManager.ERROR_NETWORK_GENERAL:
message = context.getResources().getString(R.string.err_kpe_network_general);
break;
case KnoxEnterpriseLicenseManager.ERROR_NOT_CURRENT_DATE:
message = context.getResources().getString(R.string.err_kpe_not_current_date);
break;
case KnoxEnterpriseLicenseManager.ERROR_NULL_PARAMS:
message = context.getResources().getString(R.string.err_kpe_null_params);
break;
case KnoxEnterpriseLicenseManager.ERROR_UNKNOWN:
message = context.getResources().getString(R.string.err_kpe_unknown);
break;
case KnoxEnterpriseLicenseManager.ERROR_USER_DISAGREES_LICENSE_AGREEMENT:
message = context.getResources().getString(R.string.err_kpe_user_disagrees_license_agreement);
break;
case KnoxEnterpriseLicenseManager.ERROR_LICENSE_DEACTIVATED:
message = context.getResources().getString(R.string.err_kpe_license_deactivated);
break;
case KnoxEnterpriseLicenseManager.ERROR_LICENSE_EXPIRED:
message = context.getResources().getString(R.string.err_kpe_license_expired);
break;
case KnoxEnterpriseLicenseManager.ERROR_LICENSE_QUANTITY_EXHAUSTED:
message = context.getResources().getString(R.string.err_kpe_license_quantity_exhausted);
break;
case KnoxEnterpriseLicenseManager.ERROR_LICENSE_ACTIVATION_NOT_FOUND:
message = context.getResources().getString(R.string.err_kpe_license_activation_not_found);
break;
case KnoxEnterpriseLicenseManager.ERROR_LICENSE_QUANTITY_EXHAUSTED_ON_AUTO_RELEASE:
message = context.getResources().getString(R.string.err_kpe_license_quantity_exhausted_on_auto_release);
break;
default:
// Unknown error code
String errorStatus = intent.getStringExtra(
KnoxEnterpriseLicenseManager.EXTRA_LICENSE_STATUS);
message = context.getResources()
.getString(R.string.err_kpe_code_unknown, Integer.toString(errorCode), errorStatus);
}
return message;
}
}
The KnoxEnterpriseLicenseManager
class is used to receive the KPE key, while the EnterpriseLicenseManager
class is used to receive the backwards compatible key.
Register the License Receiver class
When the KPE license is activated, the com.samsung.android.knox.intent.action.KNOX_LICENSE_STATUS
intent is emitted. Upon activation of the Backwards Compatible Key, 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 that’ll handle Knox license status broadcasts:
<receiver android:name=".SampleLicenseReceiver" >
<intent-filter>
<action android:name="com.samsung.android.knox.intent.action.KNOX_LICENSE_STATUS" />
<action android:name="com.samsung.android.knox.intent.action.LICENSE_STATUS" />
</intent-filter>
</receiver>
When your app receives the com.samsung.android.knox.intent.action.KNOX_LICENSE_STATUS
and the com.samsung.android.knox.intent.action.LICENSE_STATUS
intents, it passes the intents to SampleLicenseReceiver.onReceive()
. Use this method to have your app respond to the license activation.
Activate the license
Use this method in your MainActivity to activate the license.
private void activateLicense() {
// Instantiate the KnoxEnterpriseLicenseManager class to use the activateLicense method
KnoxEnterpriseLicenseManager licenseManager = KnoxEnterpriseLicenseManager.getInstance(this);
// License Activation TO DO - Modify Constants.KPE_LICENSE_KEY with license key to be activated
licenseManager.activateLicense(Constants.KPE_LICENSE_KEY);
mUtils.log(getResources().getString(R.string.license_progress));
}
// call backwards compatible key activation
//Backwards Compatible Key must be activated after KPE key activation.
private void activateBackwardsCompatibleKey() {
// Get an instance of the License Manager
EnterpriseLicenseManager backwardsCompatibleKeyManager = EnterpriseLicenseManager.getInstance(this);
// Activate the backwards compatible license key TO DO - Modify Constants.BACKWARDS_COMPATIBLE_KEY with BCK key to be Activated
backwardsCompatibleKeyManager.activateLicense(Constants.BACKWARDS_COMPATIBLE_KEY);
mUtils.log(getResources().getString(R.string.backwards_compatible_key_activation));
}
When you activate a license, a dialog for consent to use personal information might display. This is shown depending on the policy, and the license is activated only when confirmed. Refer to the User agreements for Android device management to find the conditions under which the Knox license privacy policy dialog is displayed.
For KLM, there are three terms that are important when it comes to licenses that you can receive in the KnoxEnterpriseLicenseManager.ACTION_LICENSE_STATUS
broadcast:
Term | Description |
---|---|
Activation | Initial license activation (Constant is integer 800) |
Deactivation | License deactivation (Constant is integer 802) |
Validation | Once or twice a day, the license agent checks to see if the license is still valid. For example, if it expires before a validation check is made, the license agent returns a value that indicates license expiration. (Constant is integer 801) |
The code from the broadcast receiver that catches the license activation is:
if (action.equals(KnoxEnterpriseLicenseManager.ACTION_LICENSE_STATUS)) {
String status = intent.getStringExtra(KnoxEnterpriseLicenseManager.EXTRA_LICENSE_STATUS);
int errorCode = intent.getIntExtra(KnoxEnterpriseLicenseManager.EXTRA_LICENSE_ERROR_CODE, 1);
int extraResult = intent.getIntExtra(KnoxEnterpriseLicenseManager.EXTRA_LICENSE_RESULT_TYPE, 1);
toast.setText("KLM Status = " + status + ", " + "Error Code= " + errorCode + ", " + "Extra Result Type= " + extraResult);
toast.show();
Log.d(TAG, "KLM Status = " + status + ", " + "Error Code= " + errorCode + ", " + "Extra Result Type= " + extraResult);
}
For example, if a validation request is made and is successful, the following toast displays:
KLM Status = Success, Error Code = 0, Extra Result Type = 801
For backwards compatible keys, there are two terms that are important when it comes to licenses that you can receive in the EnterpriseLicenseManager.ACTION_LICENSE_STATUS
broadcast:
Term | Description |
---|---|
Activation | Initial license activation (Constant is integer 800) |
Validation | Once a week, the license agent checks to see if the license is still valid. For example, if it expires before a validation check is made, the license agent returns a value that indicates license expiration. (Constant is integer 801) |
The code from the broadcast receiver that catches the license activation is:
if (action.equals(EnterpriseLicenseManager.ACTION_LICENSE_STATUS)) {
String status = intent.getStringExtra(EnterpriseLicenseManager.EXTRA_LICENSE_STATUS);
int errorCode = intent.getIntExtra(EnterpriseLicenseManager.EXTRA_LICENSE_ERROR_CODE, EnterpriseLicenseManager.ERROR_NONE);
int resultType = intent.getIntExtra(EnterpriseLicenseManager.EXTRA_LICENSE_RESULT_TYPE, EnterpriseLicenseManager.LICENSE_RESULT_TYPE_ACTIVATION);
toast.setText("BCK Status = " + status + ", " + "Error Code= " + errorCode + ", " + "Result Type= " + resultType);
toast.show();
Log.d(TAG, "BCK Status = " + status + ", " + "Error Code= " + errorCode + ", " + "Result Type= " + resultType);
}
For example, after a successful activation of a backwards compatible key, the following toast displays:
BCK Status = success, Error Code = 0, Extra Result Type = 800
Backwards Compatible Key (BCK)
You need to activate a backwards compatible key in the following cases:
KLM Type | Backwards compatible key | |
---|---|---|
Knox 2.8 or higher | Knox 2.7.1 or lower | |
KPE Standard (KLM09) | BCK not required | BCK required |
Legacy KPE Premium (KLM03, KLM06) | BCK required | BCK required |
KPE Premium (KLM09) | BCK not required | BCK required |
KLM On-Premises
A backwards compatible key is not required if your:
- device’s Knox version is 2.8 or higher
- KLM On-Premises version is 2.3 or higher
- license key was issued in 2020 or later
For all other cases, a backwards compatible key is required.
If the EMM server activates both the KPE Standard key and the backwards compatible key, it works well for all version devices even IT admin inserts any KPE premium KLM09 key or KLM03. For more information about the backwards compatible key, see What is the backwards compatible key?, Do I need to associate my app with a backwards compatible key?, When do I need to use the backwards compatible key?, and Licensing from the FAQ.
Apps can no longer activate ELM licenses on devices to call Knox APIs. Existing ELM key activated devices will remain activated, even after a factory reset. For more information see ELM License End of Service from the FAQ.
The backwards compatible key must be activated after KPE key activation.
See also:
On this tab
Before Knox 3.8, the only way to identify if a Knox license was activated or deactivated was through the use of Android Broadcast Receivers. However, due to platform system limitations, this broadcast was time consuming to receive in some situations — like a phone reboot — as each broadcast was put in a queue. From Knox SDK 3.8 onwards, a new API was included to activate and deactivate licenses in a faster way. The only difference from the current APIs is the possibility of caller applications to specify a callback that will receive the result as soon as the activation or deactivation is completed.
In the new APIs using callback, broadcasts with the activation result are no longer sent. However, activation and deactivation APIs are still supported without a callback parameter.
Activate the license
Use the following methods in your MainActivity
to activate a KPE or BCK license and to deactivate a KPE license:
//Use this method in your MainActivity to activate any KPE key.
private void activateKPELicense() {
Log.i(TAG, "activateKPELicense");
//TODO - Replace showLicenseProgressDialog with your custom loading implementation
showLicenseProgressDialog();
// Instantiate the KnoxEnterpriseLicenseManager class to use the activateLicense method
KnoxEnterpriseLicenseManager licenseManager = KnoxEnterpriseLicenseManager.getInstance(this);
// Instantiate LicenseResultCallback to handle activation result
LicenseResultCallback kpeActivationResultCallback = new LicenseResultCallbackImpl();
//TODO - Modify Constants.KPE_KEY with license key to be activated
licenseManager.activateLicense(Constants.KPE_KEY, getPackageName(), kpeActivationResultCallback);
}
//Use this method in your MainActivity to deactivate any KPE key.
private void deactivateKPELicense() {
Log.i(TAG, "deactivateKPELicense");
//TODO - Replace showLicenseProgressDialog with your custom loading implementation
showLicenseProgressDialog();
// Instantiate the KnoxEnterpriseLicenseManager class to use the deActivateLicense method
KnoxEnterpriseLicenseManager licenseManager = KnoxEnterpriseLicenseManager.getInstance(this);
// Instantiate LicenseResultCallback to handle deactivation result
LicenseResultCallback kpeDeactivationResultCallback = new LicenseResultCallbackImpl();
//TODO - Modify Constants.KPE_KEY with license key to be deactivated
licenseManager.deActivateLicense(Constants.KPE_KEY, getPackageName(), kpeDeactivationResultCallback);
}
//Use this method in your MainActivity to activate a BCK key.
//Backwards Compatible Key must be activated after KPE key activation.
private void activateBackwardsCompatibleKey() {
Log.i(TAG, "activateBackwardsCompatibleKey");
//TODO - Replace showLicenseProgressDialog with your custom loading implementation
showLicenseProgressDialog();
// Instantiate the EnterpriseLicenseManager class to use the activateLicense method
EnterpriseLicenseManager licenseManager = EnterpriseLicenseManager.getInstance(this);
// Instantiate LicenseResultCallback to handle activation result
LicenseResultCallback bckActivationResultCallback = new LicenseResultCallbackImpl();
//TODO - Modify Constants.BACKWARDS_COMPATIBLE_KEY with BCK key to be Activated
licenseManager.activateLicense(Constants.BACKWARDS_COMPATIBLE_KEY, getPackageName(), bckActivationResultCallback);
}
//Following inner class receives the callback from KPE/BCK activation and KPE deactivation
private class LicenseResultCallbackImpl implements LicenseResultCallback {
@Override
public void onLicenseResult(LicenseResult licenseResult) {
switch (licenseResult.getType()) {
case ELM_ACTIVATION:
Log.i(TAG, "BCK activation result");
handleLicenseCallbackResponse(licenseResult);
break;
case KLM_ACTIVATION:
Log.i(TAG, "KPE Activation result");
handleLicenseCallbackResponse(licenseResult);
break;
case KLM_DEACTIVATION:
Log.i(TAG, "KPE Deactivation result");
handleLicenseCallbackResponse(licenseResult);
break;
case UNDEFINED:
default:
Log.e(TAG, "Unknown error during " + licenseResult.getType());
break;
}
}
}
/**
* This method will not be called from main thread so if you need to update the UI, be sure to use the appropriate component like Handler or Activity::runOnUiThread()
*/
private void handleLicenseCallbackResponse(LicenseResult licenseResult) {
Log.i(TAG, "handleLicenseCallbackResponse");
//TODO - Replace dismissLicenseProgressDialog with your custom loading implementation
dismissLicenseProgressDialog();
if (licenseResult.isSuccess()) {
if (licenseResult.isActivation()) {
//TODO - Modify following code to handle KPE/BCK activation case
Log.i(TAG, licenseResult.getLicenseKey() +
" activated successfully");
//permissions granted can be check using following code
List permissionsGranted = licenseResult.getGrantedPermissions();
for (String permission : permissionsGranted) {
Log.i(TAG, permission);
}
} else {
//TODO - Modify following code to handle KPE deactivation case
Log.i(TAG, licenseResult.getLicenseKey() +
" deactivated successfully");
}
} else {
//TODO - Modify following code to handle error during activation/deactivation flow
Log.e(TAG, "Error during " + licenseResult.getType() + " of license key " +
licenseResult.getLicenseKey() + " with error code: " + licenseResult.getErrorCode());
}
}
When you activate a license, a dialog for consent to use personal information might display. This is shown depending on the policy, and the license is activated only when confirmed. Refer to the User agreements for Android device management to find the conditions under which the Knox license privacy policy dialog is displayed.
Backwards Compatible Key (BCK)
You need to activate a backwards compatible key in the following cases:
KLM Type | Backwards compatible key | |
---|---|---|
Knox 2.8 or higher | Knox 2.7.1 or lower | |
KPE Standard (KLM09) | BCK not required | BCK required |
Legacy KPE Premium (KLM03, KLM06) | BCK required | BCK required |
KPE Premium (KLM09) | BCK not required | BCK required |
KLM On-Premises
A backwards compatible key is not required if your:
- device’s Knox version is 2.8 or higher
- KLM On-Premises version is 2.3 or higher
- license key was issued in 2020 or later
For all other cases, a backwards compatible key is required.
If the EMM server activates both the KPE Standard key and the backwards compatible key, it works well for all version devices even IT admin inserts any KPE premium KLM09 key or KLM03. For more information about the backwards compatible key, see What is the backwards compatible key?, Do I need to associate my app with a backwards compatible key?, When do I need to use the backwards compatible key?, and Licensing from the FAQ.
Apps can no longer activate ELM licenses on devices to call Knox APIs. Existing ELM key activated devices will remain activated, even after a factory reset. For more information see ELM License End of Service from the FAQ.
The backwards compatible key must be activated after KPE key activation.
See also:
Is this page helpful?
Thank you for your feedback!