集成您的应用
对于Amazon Device Messaging(ADM),在获取凭证并在您的开发环境中完成设置之后,请将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 TV设备的其他系统版本均支持ADM。
更新您的应用清单
接收通过 ADM 发送的消息的第一步就是更新您的 AndroidManifest.xml 文件。您必须对现有文件进行以下更改。
-
打开AndroidManifest.xml文件并添加Amazon命名空间:
xmlns:amazon="http://schemas.amazon.com/apk/res/android"
-
要声明支持ADM所需的权限,请在
manifest
元素后面添加permission
和uses-permission
元素。<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:amazon="http://schemas.amazon.com/apk/res/android" package="[您的程序包名称]" android:versionCode="1" android:versionName="1.0"> <!-- 此权限将确保任何其他应用均无法拦截您的ADM消息。--> <permission android:name="[您的程序包名称].permission.RECEIVE_ADM_MESSAGE" android:protectionLevel="signature" /> <uses-permission android: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>
-
显式启用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"/> ...
-
声明一个广播接收器以处理ADM发送的
REGISTRATION
和RECEIVE
意图。ADM要求在AndroidManifest.xml文件中定义该接收器,而不是以编程方式定义。在amazon:enable-feature
后面添加以下元素。<!-- You must replace the names in the service and receiver tags 适合您程序包的名称。 -->D <service android:name="[您的JOBSERVICE名称]" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="false" /> <!-- ADM版本比较旧的设备需要此设置--> <service android:name="[您的服务名称]" android:exported="false" /> <receiver android: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="[您的程序包名称]" /> </intent-filter> </receiver>
-
更新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="[您的程序包名称]"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<permission
android:name="[您的程序包名称].permission.RECEIVE_ADM_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android: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="[您的JOBSERVICE名称]"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" />
<!-- ADM版本比较旧的设备需要此设置-->
<service
android:name="[您的服务名称]"
android:exported="false" />
<receiver
android: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="[您的程序包名称]" />
</intent-filter>
</receiver>
</application>
</manifest>
将您的API密钥存储为资产
您的应用必须包含有效的API密钥才能接收消息。获取凭证介绍了创建API密钥的过程,而ADM概览更加详细地介绍了API密钥。
对于应用的预发布或“调试”版本,您必须创建API密钥并将其存储在您的项目中。要在您的应用中添加API密钥:
- 在项目的assets文件夹内创建一个名为
api_key.txt
的文件。必须将该文件放置在此特定目录中。 - 插入API密钥作为此
api_key.txt
文件中的唯一数据。
对于应用的发布或“生产”版本,如果应用使用Appstore SDK,则必须为应用的发布版本创建额外的API密钥。如果使用较旧的IAP SDK v2.0,并使用自己的证书为应用签名,您还必须为应用的发布版本创建API密钥。反之,如果使用IAP SDK v2.0,或者完全不使用应用内购买SDK,并且允许亚马逊代表您为应用签名,则无需创建额外的API密钥。如需查看摘要,请参阅下表:
使用Appstore SDK的应用 | 用您自己的证书签名的应用 | 需要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()
。如果这是在给定设备上首次启动应用或者以前的注册失败,此代码便会开始注册过程。
实现注册和消息处理
ADM有三个类必须扩展。请参阅下表以了解每个类的功能。也可以查看ADM API参考。
类 | 描述 |
---|---|
com.amazon.device.messaging.ADMMessageHandlerJobBase |
用于处理最新Fire设备上的消息 |
com.amazon.device.messaging.ADMMessageHandlerBase |
用于处理较旧Fire设备上的消息 |
com.amazon.device.messaging.ADMMessageReceiver |
用于将消息转发到相应的消息处理类 |
清单中所声明的广播接收器会侦听意图,并在意图到达时调用应用。应用通过com.amazon.device.messaging.ADMMessageHandlerJobBase
和com.amazon.device.messaging.ADMMessageHandlerBase
类中定义的下述回调方法与广播接收器进行通信:
回调方法 | 描述 |
---|---|
onRegistered |
在应用实例的注册ID准备就绪时调用。应用必须将此注册ID传输到您的服务器。这样做可让您的服务器向该应用实例发送消息。 |
onUnregistered |
在应用实例已从ADM注销时调用。 |
onRegistrationError |
在应用的ADM注册请求因任意原因(例如,没有亚马逊用户登录设备)而失败时调用。 |
onMessage |
在ADM客户端将消息传送到您的应用实例时调用。 |
实现com.amazon.device.messaging.ADMMessageHandlerJobBase
、com.amazon.device.messaging.ADMMessageHandlerBase
和com.amazon.device.messaging.ADMMessageReceiver
的子类时,应用必须覆盖这些回调,如以下代码示例所示:
-
检查是否已更新当前设备以支持新的ADM服务。
ADMLatestAvailable = false ; try{ Class.forName( "com.amazon.device.messaging.ADMMessageHandlerJobBase" ); ADMLatestAvailable = true ; } catch (ClassNotFoundException e) { // 处理异常。 }
-
创建您的接收器和服务实现。
public class Receiver extends ADMMessageReceiver { public Receiver() { // 这是向后兼容所需的 super(MyADMLegacyMessageHandler.class); // 若可能,推荐使用基于新作业的 if (ADMLatestAvailable) { registerJobServiceClass(MyADMMessageHandler.class, <JOB_ID>) } } // 此处不需要其他内容;广播接收器会将意图自动 // 转发到您的服务以进行处理。 }
public class MyADMMessageHandler extends ADMMessageHandlerJobBase { @Override protected void onRegistered(final Context context, final String newRegistrationId) { // 通过在主要活动中调用startRegister()来启动注册 // 过程。当注册ID就绪时,ADM将对您的应用 // 调用onRegistered()。将传入的注册ID传输到您的服务器,以便 // 服务器可以将消息发送到此应用实例。如果 // 您的注册ID因任何原因发生轮换或更改,ADM也会调用onRegistered(); // 如果出现这种情况,您的应用应将新的注册ID传递到您的服务器。 // 您的服务器需要能够处理长达1536个字符的 // 注册ID。 // 在以下示例中,注册ID通过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 Context context, final String registrationId) { //如果您的应用在此台设备上已注销,请通知服务器 // 此应用实例不再是有效的消息发送目标。 } @Override protected void onRegistrationError(final Context context, final String errorId) { // 注册错误应视为严重错误。因此,您的应用可 // 正常降级,或者您可通知用户 // 应用的这项功能不可用。 } @Override protected void onMessage(final Context context, 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); } }
public class MyADMLegacyMessageHandler extends ADMMessageHandlerBase
{
@Override
protected void onRegistered(final String newRegistrationId)
{
// 通过在主要活动中调用startRegister()来启动注册
// 过程。当注册ID就绪时,ADM将对您的应用
// 调用onRegistered()。将传入的注册ID传输到您的服务器,以便
// 服务器可以将消息发送到此应用实例。如果
// 您的注册ID因任何原因发生轮换或更改,ADM也会调用onRegistered();
// 如果出现这种情况,您的应用应将新的注册ID传递到您的服务器。
// 您的服务器需要能够处理长达1536个字符的
// 注册ID。
// 在以下示例中,注册ID通过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)
{
// 如果您的应用在此台设备上已注销,请通知服务器
// 此应用实例不再是有效的消息发送目标。
}
@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的情况,这样即可让您在不一定包含ADM的设备中安装并运行单一APK。
若想修改您的应用以正常降级,
-
请使用如下所示的代码检查ADM。
ADMAvailable = false ; try { Class.forName( "com.amazon.device.messaging.ADM" ); ADMAvailable = true ; } catch (ClassNotFoundException e) { // 处理异常。 }
-
将以下代码添加到所有需要ADM库运行时的代码中。
if (ADMAvailable) { // 在此处放置需要ADM的代码。 }
-
在AndroidManifest.xml文件中,确认应用元素指定了以下内容:
amazon:enable-feature android:name="com.amazon.device.messaging" android:required="false"
测试ADM集成
可以通过向设备发送测试通知来确认应用完成了ADM集成设置。有关更多信息,请参阅发送消息。
Last updated: 2022年4月14日