集成您的应用


集成您的应用

获取凭证以便使用 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 电视设备上,所有系统版本均支持 ADM。

更新您的应用清单

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

  1. 添加 Amazon 命名空间。

    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">
    <!-- This permission ensures that no other application can intercept your
    ADM messages. -->
    <permission
         android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE"
         android:protectionLevel="signature" />
    <uses-permission android:name="[YOUR PACKAGE NAME].permission.RECEIVE_ADM_MESSAGE" />
    
    <!-- This permission allows your app access to receive push notifications
    from ADM. -->
    <uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" />
    
    <!-- ADM uses WAKE_LOCK to keep the processor from sleeping when a message is received. -->
    <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">
    
          <!-- You must explicitly enable ADM and declare whether your app cannot work without
             ADM (android:required="true") or can work without ADM (android:required="false").
             If you specify android:required="false", your app must degrade gracefully if ADM
             is unavailable. -->
             <amazon:enable-feature
    	  android:name="com.amazon.device.messaging"
                 android:required="true"/>
    ...
    
  4. 声明一个广播接收器以处理 ADM 发送的 REGISTRATIONRECEIVE 意图。ADM 要求在 AndroidManifest.xml 文件中而不是以编程方式定义该接收器。紧跟在 amazon:enable-feature 后面添加以下元素。

     <!-- You must replace the names in the service and receiver tags
         with names that are appropriate to your package. -->
    
     <service
         android:name="[YOUR SERVICE NAME]"
         android:exported="false" />
    
     <receiver
         android:name="[YOUR RECEIVER NAME]"
    
         <!-- This permission ensures that only ADM can send your app registration broadcasts. -->
         android:permission="com.amazon.device.messaging.permission.SEND" >
    
         <!-- To interact with ADM, your app must listen for the following intents. -->
         <intent-filter>
     <action android:name="com.amazon.device.messaging.intent.REGISTRATION" />
     <action android:name="com.amazon.device.messaging.intent.RECEIVE" />
    
     <!-- Replace the name in the category tag with your app's package name. -->
     <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_key.txt 的文件中。该 api_key.txt 文件位于您项目的 assets 文件夹内。

对于正式发布或“生产”版本的应用,您可能不需要创建 API 键。​仅当您使用自己的证书对正式发布版本的应用进行签名时,才必须为该应用创建额外的 API 键。否则,如果您允许 Amazon 代表您对应用进行签名,则无需创建额外的 API 键。

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

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

  • 创建 ADM 上下文的实例
  • 启动此应用实例向 ADM 的注册
final ADM adm = new ADM(this);
if (adm.getRegistrationId() == null)
{
   // startRegister() is asynchronous; your app is notified via the
   // onRegistered() callback when the registration ID is available.
   adm.startRegister();
}

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

实施注册和消息处理

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

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

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

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

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

    // Nothing else is required here; your broadcast receiver automatically
    // forwards intents to your service for processing.
    }

    @Override
    protected void onRegistered(final String newRegistrationId)
        {
        // You start the registration process by calling startRegister() in your Main
        // Activity.When the registration ID is ready, ADM calls onRegistered() on
        // your app.Transmit the passed-in registration ID to your server, so your
        // server can send messages to this app instance. onRegistered() is also
        // called if your registration ID is rotated or changed for any reason; your
        // app should pass the new registration ID to your server if this occurs.
        // Your server needs to be able to handle a registration ID up to 1536 characters
        // in length.

        // The following is an example of sending the registration ID to your
        // server via a header key/value pair over HTTP.
        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)
    {
        // If your app is unregistered on this device, inform your server that
        // this app instance is no longer a valid target for messages.
    }

    @Override
    protected void onRegistrationError(final String errorId)
    {
        // You should consider a registration error fatal.In response, your app may
        // degrade gracefully, or you may wish to notify the user that this part of
        // your app's functionality is not available.
    }

    @Override
    protected void onMessage(final Intent intent)
    {
        // Extract the message content from the set of extras attached to
        // the com.amazon.device.messaging.intent.RECEIVE intent.

        // Create strings to access the message and timeStamp fields from the JSON data.
        final String msgKey = getString(R.string.json_data_msg_key);
        final String timeKey = getString(R.string.json_data_time_key);

        // Obtain the intent action that will be triggered in onMessage() callback.
        final String intentAction = getString(R.string.intent_msg_action);

        // Obtain the extras that were included in the intent.
        final Bundle extras = intent.getExtras();

        // Extract the message and time from the extras in the intent.
        // ADM makes no guarantees about delivery or the order of messages.
        // Due to varying network conditions, messages may be delivered more than once.
        // Your app must be able to handle instances of duplicate messages.
        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 的情况,您可以构建在可包含或无法包含 ADM 的设备上安装并运行的单个 APK。

修改您的应用以正常降级

  1. 使用类似如下的代码检查 ADM。

    ADMAvailable = false ;
    try
    {
        Class.forName( "com.amazon.device.messaging.ADM" );
        ADMAvailable = true ;
    }
    catch (ClassNotFoundException e)
    {
        // Handle the exception.
    }
    
  2. 将以下代码添加到需要 ADM 库运行时的任意代码中。

    if (ADMAvailable)
    {
        // Your code that requires ADM goes here.
    }
    
  3. AndroidManifest.xml 文件中,验证应用元素是否指定以下内容:

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