Developer Console

DRM for Android

DRM (digital rights management, or more generally license verification), is used to address developer concerns around unauthorized copying and distribution of your app. When you implement DRM in your app, you ensure that only users who purchased your app can install it on the authorized device.

License checking overview

The DRM API allows you to check whether the user is licensed for the content. The Appstore client looks for an appropriate content license in the app's local cache. If the license is found in the local cache, it will be returned in the response. (Hence even if a user is offline, the app will still run.) If the license does not exist in the cache, the Appstore client will call the Appstore to retrieve the content license.

You will need to use the DRM API to initiate the license checking and then apply logic to authorize or deny the user based on the status of the license returned by Amazon.

DRM in Appstore SDK

Previously, when you uploaded Android APKs into the Amazon Appstore, you had the option to select Yes or No for "Apply Amazon DRM?" as shown in the following screenshot:

If you selected Yes, Amazon would add DRM to your app.

With the Appstore SDK, the Developer Console no longer displays this option. If you want to add DRM to your APK, use the DRM API (included in the Appstore SDK) to incorporate license checking in your app.

If you haven't upgraded to the Appstore SDK, but use an older IAP SDK (or aren't using IAP), the option to "Allow Amazon to Apply DRM?" appears after uploading your APK.

Warning messages

If you upload an APK that uses an older IAP SDK version or no SDK at all, then you will see the following warning:

DRM sample app

A DRM sample app and tutorial is available showing the DRM API code in a simple integration.

Implement DRM in your app

To implement DRM in your app, do the following:

  1. Follow the instructions in Integrate the Appstore SDK to add the Appstore SDK into your Android project.

  2. Update your app's manifest file.
    1. Add an entry for the ResponseReceiver to your manifest. The following code example shows how to add a ResponseReceiver to the AndroidManifest.xml file for DRM. If your app targets Android 12 or higher, you must explicitly set android:exported to true in the MainActivity and ResponseReceiver as shown in the following example:

        <application>
        ...
           <activity android:label="@string/app_name" android:name="com.amazon.sample.drm.MainActivity" 
                       android:exported="true">
                 <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                 </intent-filter>
           </activity>
      
           <receiver android:name = "com.amazon.device.drm.ResponseReceiver" android:exported="true" 
                       android:permission = "com.amazon.drm.Permission.NOTIFY" >
                 <intent-filter>
                    <action android:name = "com.amazon.drm.NOTIFY" />
                 </intent-filter>
           </receiver>
        ...
        </application>
      
    2. If your app targets Android API level 30 or higher, you must define the list of packages your app needs to query in the AndroidManifest.xml file. To be able to query Amazon App Tester and Amazon Appstore, add the following code to your manifest file.

        <manifest>
        ...
           <queries>
              <package android:name="com.amazon.sdktestclient" />
              <package android:name="com.amazon.venezia" />
           </queries>
        </manifest>
      
  3. Initiate the license verification by calling verifyLicense(). This method is exposed in the LicensingService class. It takes two parameters as input:

    • ApplicationContext
    • Your implementation of LicensingListener

    When your app launches, initiate license verification. You can initiate the license verification with either of the following methods:

    • onCreate() method of your MainActivity
    • onCreate() of a custom implementation of the Application class

    Here's an example:

    LicensingService.verifyLicense(getApplicationContext(), new LicenseVerificationCallback(this));
    
  4. Implement LicensingListener.

    LicensingListener defines a single method: onLicenseCommandResponse(final LicenseResponse licenseResponse). This method is called by the Appstore SDK after it receives the result of the verifyLicense() call from Amazon Appstore. LicenseResponse will contain the status of verifyLicense() call. The response will contain one of the following statuses:

    • LICENSED
    • NOT_LICENSED
    • ERROR_VERIFICATION
    • ERROR_INVALID_LICENSING_KEYS
    • EXPIRED
    • UNKNOWN_ERROR

    For descriptions about each status and the reasons, see License statuses.

    A basic implementation of LicensingListener interface is as follows. (This code merely logs the returned status of the license.)

    public class LicenseVerificationCallback implements com.amazon.device.drm.LicensingListener {
      public void onLicenseCommandResponse(final LicenseResponse licenseResponse) {
             final LicenseResponse.RequestStatus status = licenseResponse.getRequestStatus();
             Log.d(TAG, "onLicenseCommandResponse: RequestStatus (" + status + ")");
             switch (status) {
                   case LICENSED:
                        Log.d(TAG, "onLicenseCommandResponse: LICENSED");
                        break;
                   case NOT_LICENSED:
                         Log.d(TAG, "onLicenseCommandResponse: NOT_LICENSED");
                         break;
                   case ERROR_VERIFICATION:
                         Log.d(TAG, "onLicenseCommandResponse: ERROR_VERIFICATION");
                         break;
                   case ERROR_INVALID_LICENSING_KEYS:
                         Log.d(TAG, "onLicenseCommandResponse: ERROR_INVALID_LICENSING_KEYS");
                         break;
                   case EXPIRED:
                         Log.d(TAG, "onLicenseCommandResponse: EXPIRED");
                         break;
                   case UNKNOWN_ERROR:
                         Log.d(TAG, "onLicenseCommandResponse: ERROR");
    } } }
    

License statuses

When you call verifyLicense(), the licensing service sends back one of the license statuses defined in the following table.

License Status Description
LICENSED The user has a valid license.
NOT_LICENSED The user does not have a valid license. He or she is not entitled to use the application.
ERROR_VERIFICATION There was an error in trying to verify the license. Reasons for the verification error might be due to the following:
  • Amazon was not able to validate the metadata of the app (such as the checksum, signature, package name, etc).
  • The license received by the "Appstore SDK" (or potentially a fake masquerading as such) has been tampered with during transit.
ERROR_INVALID_LICENSING_KEYS The user has license keys but they are not valid. Reasons for the invalid licensing keys might be due to the following:
  • You did not add the public key to your app, or you added it to the incorrect folder.
  • The public key you added does not match the corresponding private key that is with Amazon.
EXPIRED

The user's license has expired and the user's current license is now not valid. A license is valid for 60 days. After 30 days, the Appstore tries to renew the license every 24 hours.

If the user is offline for more than 60 days, the Appstore will be unable to renew the license before it expires. If the license expires, the app will no longer launch for the customer.

Other reasons for expired licenses might be due to the following:

  • The customer might have requested cancellation of his or her order.
  • The Appstore fulfilled the customer's order optimistically (before the payment transaction was finalized), but later the charge failed so the license was revoked.

UNKNOWN_ERROR This status indicates an internal error at Amazon's end.

DRM library obfuscation

Most of the Appstore SDK library is already obfuscated (before it was packaged into a JAR). However, some developer-facing classes are not obfuscated. The following DRM library classes are not obfuscated:

  • LicensingListener
  • LicensingService
  • LicenseResponse
  • RequestId

If you want to keep these classes from being obfuscated, add the appropriate references in your ProGuard file to exclude them (assuming you're using ProGuard to obfuscate your code).


Last updated: Sep 05, 2024