开发者控制台

适用于Android的DRM

适用于Android的DRM

DRM(数字版权管理,也常被称为许可证验证)用于解决开发者对未经授权复制和分发应用的后顾之忧。如果在应用中实现DRM,就能确保只有购买应用的用户可以在授权的设备上安装该应用。

许可证检查概述

通过DRM API可以检查用户是否获得了内容许可证。亚马逊应用商店客户端会在应用的本地缓存中查找相应的内容许可证。如果在本地缓存中找到了许可证,则会在响应中将其返回。(因此,即使用户处于离线状态,应用仍然可以运行。) 如果缓存中没有许可证,亚马逊应用商店客户端将调用Appstore,以检索内容许可证。

您需要使用DRM API启动许可证检查,然后根据亚马逊返回的许可证状态应用逻辑,对用户进行授权或予以拒绝。

Appstore SDK中的DRM

以前,将Android APK上传至亚马逊应用商店后,可以为“应用亚马逊DRM?”选择。如果选择,则亚马逊会为您的应用添加DRM。

使用Appstore SDK,开发者控制台不会再显示此选项。如果想要为APK添加DRM,请使用DRM API(包含在Appstore SDK中)在您的应用中引入许可证检查。

如果尚未升级为Appstore SDK,但使用了较早的IAP SDK版本(或者没有使用IAP),则上传APK后,系统会显示 “是否允许亚马逊应用DRM?”选项。

警告消息

如果上传的APK使用了较早的IAP SDK版本或者根本没有使用SDK,则显示以下警告。

您的应用文件使用了过时的SDK版本,其中不包含DRM集成。请选择上面的DRM首选项。如果希望在代码中添加DRM支持,请使用Appstore SDK。

DRM示例应用

提供了DRM示例应用和教程,通过简单的集成展示了DRM API代码。

在应用中实现DRM

要在应用中实现DRM,请执行以下操作:

  1. 按照集成Appstore SDK中的说明,将Appstore SDK添加到您的Android项目中。

  2. 更新应用的清单文件。
    1. 向清单中添加ResponseReceiver的条目。以下代码示例展示了如何在DRM的AndroidManifest.xml文件中添加ResponseReceiver。如果您的应用以Android 12或更高版本为目标,则必须在MainActivityResponseReceiver中显式地将android:exported设置为true,如下面的示例所示:

        <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. 如果您的应用以Android API级别30或更高级别为目标,则必须在AndroidManifest.xml文件中定义应用需要查询的程序包列表。要想能够查询Amazon App Tester和亚马逊应用商店,请将以下代码添加到您的清单文件中。

        <manifest>
        ...
           <queries>
              <package android:name="com.amazon.sdktestclient" />
              <package android:name="com.amazon.venezia" />
           </queries>
        </manifest>
      
  3. 调用verifyLicense(),启动许可证验证。此方法已在LicensingService类中公开。它将两个参数作为输入:

    • ApplicationContext
    • LicensingListener的实现

    当应用启动时,启动许可证验证。可以使用以下任一方法启动许可证验证:

    • MainActivityonCreate()方法
    • Application类自定义实现中的onCreate()

    示例如下:

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

    LicensingListener定义单一方法:onLicenseCommandResponse(final LicenseResponse licenseResponse)。在收到来自亚马逊应用商店verifyLicense()调用的结果后,Appstore SDK会调用此方法。LicenseResponse将包含verifyLicense()调用的状态。响应将包含下列状态之一:

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

    有关每种状态和原因的描述,请参阅许可证状态

    LicensingListener接口的基本实现方法如下所示。(此代码仅记录许可证的返回状态。)

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

许可证状态

在调用verifyLicense()时,许可证服务会发回下表中定义的许可证状态之一。

许可证状态 描述
LICENSED 用户拥有有效的许可证。
NOT_LICENSED 用户没有有效的许可证。用户无权使用该应用。
ERROR_VERIFICATION 尝试验证许可证时出错。验证错误可能由以下原因造成:
  • 亚马逊无法验证应用的元数据(例如校验和、签名、程序包名称等)。
  • “Appstore SDK”(也可能为仿冒)接收的许可证在传输过程中遭到篡改。
ERROR_INVALID_LICENSING_KEYS 用户拥有许可证密钥,但密钥无效。许可证密钥无效可能由以下原因造成:
  • 您没有将公有密钥添加到应用,或者将其添加到了错误的文件夹中。
  • 您添加的公有密钥与亚马逊相应的私有密钥不匹配。
EXPIRED

用户的许可证已过期,用户当前的许可证无效。许可证有效期为60天。30天后,亚马逊应用商店每24小时会尝试一次续订许可证。

如果用户离线超过60天,则亚马逊应用商店将无法在许可证过期之前完成续订。如果许可证过期,客户将无法再启动该应用。

许可证过期也可能由以下原因造成:

  • 客户可能已经请求取消其订单。
  • 亚马逊应用商店在付款交易最终完成前,乐观地履行了客户的订单,但之后收费失败,因此撤销了许可证。

UNKNOWN_ERROR 此状态表示亚马逊端出现了内部错误。

DRM库混淆处理

Appstore SDK库中的大部分内容已经过混淆处理(在打包到JAR前)。但是,一些面向开发者的类不会进行混淆处理。以下DRM库的类不会进行混淆处理:

  • LicensingListener
  • LicensingService
  • LicenseResponse
  • RequestId

如果想要防止混淆处理这些类别,请在ProGuard文件中添加适当的引用以将其排除(假设您使用ProGuard对代码进行混淆处理)。


Last updated: 2024年12月4日