集成您的应用


集成您的应用

在为使用Amazon Device Messaging (ADM)获取凭证并在您的开发环境中完成安装之后,您需要将ADM与您的应用集成在一起。要大致了解如何编写应用和服务器代码以采用ADM,请参阅概览

测试说明

在测试您的应用使用ADM的情况时,请注意以下几点:

  • 第一代Kindle Fire平板电脑不支持ADM。
  • 第二代Kindle Fire平板电脑必须运行以下系统版本才支持ADM。要查看系统版本,请转到Settings > Device > About(设置 > 设备 > 关于)。
    • Kindle Fire HD 8.9" - 系统版本8.3.0或更高版本
    • Kindle Fire HD 7" - 系统版本7.3.0或更高版本
    • Kindle Fire(第二代)- 系统版本10.3.0或更高版本。在第二代平板电脑上,您的企业防火墙可能会阻止对ADM进行网络访问。您的应用必须能够使用UDP通过以下任一端口与您企业网络之外的服务器进行通信:

      • 49317
      • 33434
      • 40317
  • 在其他Fire平板电脑、Fire手机和Fire TV设备上,所有系统版本均支持ADM。

更新您的应用清单

要接收通过ADM发送的消息,第一步是更新AndroidManifest.xml文件。您必须对现有文件进行以下更改。

  1. 打开AndroidManifest.xml文件并添加亚马逊命名空间:

    xmlns:amazon="http://schemas.amazon.com/apk/res/android"
    
  2. 要声明支持ADM所需的权限,请在manifest元素后面添加permissionuses-permission元素。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:amazon="http://schemas.amazon.com/apk/res/android"
       package="[YOUR PACKAGE NAME]"
       android:versionCode="1"
       android:versionName="1.0">
    <!-- 此权限将确保任何其他应用均无法拦截
    ADM消息。 -->
    <permission
         android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE"
         android:protectionLevel="signature" />
    <uses-permission android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE" />
    
    <!-- 此权限允许您的应用接收
    来自ADM的推送通知。 -->
    <uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" />
    
    <!--ADM使用WAKE_LOCK来防止在收到消息时处理器处于睡眠状态。 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    ...
    </manifest>
    
  3. 显式启用ADM并声明,您的应用是需要ADM才能工作(android:required="true"),还是在ADM不存在的情况下也可以工作(android:required="false")。如果您指定android:required="false",则您的应用必须在ADM不可用的情况下正常降级。在清单的application节点中,添加amazon:enable-feature元素。

    ...
    <application
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme">
    
          <!-- 您必须显式启用ADM并声明,您的应用是在没有
             ADM的情况下无法工作(android:required="true"),还是在没有ADM的情况下可以工作(android:required="false")。
             如果您指定android:required="false",则您的应用在ADM不可用的情况下
             必须正常降级。 -->
             <amazon:enable-feature
    	  android:name="com.amazon.device.messaging"
                 android:required="true"/>
    ...
    
  4. 声明一个广播接收器以处理ADM发送的REGISTRATIONRECEIVE意图。ADM要求在AndroidManifest.xml文件中定义该接收器,而不是以编程方式定义。紧跟在amazon:enable-feature后面添加以下元素。

     <!-- 您必须将服务和接收器标签中的名称替换为
         适用于您的程序包的名称。 -->
    
     <service
         android:name="[YOUR SERVICE NAME]"
         android:exported="false" />
    
     <receiver
         android:name="[YOUR RECEIVER NAME]"
    
         <!-- 此权限可确保只有ADM可以发送您的应用注册广播。 -->
         android:permission="com.amazon.device.messaging.permission.SEND" >
    
         <!-- 若要与ADM交互,您的应用必须侦听以下意图。 -->
         <intent-filter>
     <action android:name="com.amazon.device.messaging.intent.REGISTRATION" />
     <action android:name="com.amazon.device.messaging.intent.RECEIVE" />
    
     <!-- 将类别标签中的名称替换为您的应用程序包名称。 -->
     <category android:name="[YOUR PACKAGE NAME]" />
         </intent-filter>
     </receiver>
    
  5. 更新AndroidManifest.xml文件后,您可以通过调用ADMManifest.checkManifestAuthoredProperly()来确认这些更改是否适合ADM。

    如果收到java.lang.NoClassDefFoundError: com.amazon.device.messaging.ADM错误,请检查清单,确认已将amazon:enable-feature元素添加到步骤3中指定的位置。

以下代码是为ADM启用的AndroidManifest.xml文件的完整示例。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:amazon="http://schemas.amazon.com/apk/res/android"
   package="[YOUR PACKAGE NAME]"
   android:versionCode="1"
   android:versionName="1.0" >

   <uses-sdk
      android:minSdkVersion="15"
      android:targetSdkVersion="15" />

   <permission
      android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE"
      android:protectionLevel="signature" />
   <uses-permission android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE" />

   <uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" />

   <uses-permission android:name="android.permission.WAKE_LOCK" />

   <application
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" >

      <amazon:enable-feature
         android:name="com.amazon.device.messaging"
         android:required="true"/>

      <service
         android:name="[YOUR SERVICE NAME]"
         android:exported="false" />

      <receiver
         android:name="[YOUR RECEIVER NAME]"
         android:permission="com.amazon.device.messaging.permission.SEND" >

         <intent-filter>
         <action android:name="com.amazon.device.messaging.intent.REGISTRATION" />
         <action android:name="com.amazon.device.messaging.intent.RECEIVE" />

         <category android:name="[YOUR PACKAGE NAME]" />
         </intent-filter>

      </receiver>
   </application>
</manifest>

将您的API密钥存储为资产

要让您的应用能够接收消息,该应用必须包含有效的API密钥。获取凭证介绍了创建API密钥的过程,而概览更加详细地讨论了API密钥。

对于应用的预发布或“调试”版本,您必须创建API密钥并将其存储在您的项目中。要将API密钥添加到您的应用:

  1. 在项目的assets文件夹内创建一个名为api_key.txt的文件。必须将该文件放置在此特定目录中。
  2. 插入API密钥作为此api_key.txt文件中的唯一数据。

对于应用的发布或“生产”版本,您可能不需要创建API密钥。但如果您使用自己的证书对应用的发布版本进行签名,则您必须为应用的发布版本创建一个额外的API密钥。反之,如果您允许亚马逊代表您对您的应用进行签名,则无需创建额外的API密钥。

将ADM集成到您应用的主要活动中

以下代码示例显示了如何使用com.amazon.device.messaging.ADM类中的方法执行以下操作:

  • 创建ADM上下文的实例
  • 启动此应用实例向ADM的注册
final ADM adm = new ADM(this);
if (adm.getRegistrationId() == null)
{
   // startRegister()是异步的;当注册ID可用时,
   // 将通过onRegistered()回调通知您的应用。
   adm.startRegister();
}

每次您的应用启动时,您都应运行此代码;例如,通过将其放入onCreate()方法来运行。如果您的应用已注册,getRegistrationId()会返回此应用实例的注册ID,而不会调用startRegister()。如果这是在给定设备上首次启动应用或者以前的注册失败,此代码便会开始注册过程。

实现注册和消息处理

您的清单中所声明的广播接收器会侦听意图,并在意图到达时调用您的应用。您的应用会通过com.amazon.device.messaging.ADMMessageHandlerBase类中定义的以下回调方法,与广播接收器进行通信:

  • onRegistered。在应用实例的注册ID准备就绪时调用。您的应用必须将此注册ID传输到服务器。这样做可以使您的服务器将消息发送到应用实例

  • onUnregistered。在应用实例已从ADM注销时调用。

  • onRegistrationError。在应用的ADM注册请求因某一原因(例如,亚马逊用户未登录设备)而失败时调用。

  • onMessage。在ADM客户端将消息传送到应用实例时调用。

当您实现com.amazon.device.messaging.ADMMessageHandlerBasecom.amazon.device.messaging.ADMMessageReceiver的子类时,您的应用必须覆盖这些回调,如以下代码示例中所示:

public class MyADMMessageHandler extends ADMMessageHandlerBase
{
    public static class Receiver extends ADMMessageReceiver
    {
        public Receiver()
        {
            super(MyADMMessageHandler.class);
        }

    // 此处不需要其他内容;广播接收器会将意图自动
    // 转发到您的服务以进行处理。
    }

    @Override
    protected void onRegistered(final String newRegistrationId)
        {
        // 通过在主要活动中调用startRegister()来启动注册
        // 过程。当注册ID就绪时,ADM将对您的应用
        // 调用onRegistered()。将传入的注册ID传输到您的服务器,以便
        // 服务器可以将消息发送到此应用实例。如果
        // 您的注册ID因任何原因发生轮换或更改,ADM也会调用onRegistered();
        // 如果出现这种情况,您的应用应将新的注册ID传递到您的服务器。
        // 您的服务器需要能够处理长达1536个字符的
        // 注册ID。

        // 下面是一个示例,它借助标头键/值对通过
        // HTTP将注册ID发送到您的服务器。
        URL url = new URL(YOUR_WEBSERVER_URL);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setDoInput(true);
        con.setUseCaches(false);
        con.setRequestMethod("POST");
        con.setRequestProperty("RegistrationId", newRegistrationId);
        con.getResponse();
        }

    @Override
    protected void onUnregistered(final String registrationId)
    {
        // 如果您的应用在此台设备上注销,请通知服务器
        // 此应用实例不再是有效的消息发送目标。
    }

    @Override
    protected void onRegistrationError(final String errorId)
    {
        // 您应将注册错误视为严重错误。作为响应,您的应用可能会
        // 正常降级,或者您可能需要通知用户,
        // 您的应用的这部分功能不再可用。
    }

    @Override
    protected void onMessage(final Intent intent)
    {
        // 从附加到com.amazon.device.messaging.intent.RECEIVE意图
        // 的额外信息集中提取消息内容。

        // 创建字符串以访问JSON数据中的message和timeStamp字段。
        final String msgKey = getString(R.string.json_data_msg_key);
        final String timeKey = getString(R.string.json_data_time_key);

        // 获取将在onMessage()回调中触发的意图操作。
        final String intentAction = getString(R.string.intent_msg_action);

        // 获取包含在意图中的额外信息。
        final Bundle extras = intent.getExtras();

        // 从意图中的额外信息中提取消息和时间。
        // ADM不保证消息能够送达,也不保证消息按顺序送达。
        // 由于网络条件不同,消息可能会被投递多次。
        // 您的应用必须能够处理出现重复消息时的情况。
        final String msg = extras.getString(msgKey);
        final String time = extras.getString(timeKey);
    }
}

在ADM不可用时正常降级

在清单文件中,您将声明您的应用在没有ADM的情况下能工作(android:required="false")还是不能工作(android:required="true")。如果您指定android:required="false",则您的应用必须在ADM不可用的情况下正常降级。

通过将应用设计为适应缺少ADM的情况,您只需构建一个APK,无论设备是否包含ADM,该APK均可在其上安装并运行。

修改您的应用以正常降级

  1. 使用如下所示的代码检查ADM。

    ADMAvailable = false ;
    try
    {
        Class.forName( "com.amazon.device.messaging.ADM" );
        ADMAvailable = true ;
    }
    catch (ClassNotFoundException e)
    {
        // 处理异常。
    }
    
  2. 将以下代码添加到所有需要ADM库运行时的代码中。

    if (ADMAvailable)
    {
        // 在此处放置需要ADM的代码。
    }
    
  3. AndroidManifest.xml文件中,确认应用元素指定了以下内容:

    amazon:enable-feature android:name="com.amazon.device.messaging" android:required="false" /