亚马逊Kindle设备如何通过FCM获取设备令牌?
解决Kindle设备无法获取FCM令牌的问题
这个问题我碰到过好多次了——Kindle Fire系列设备默认没有预装Google Play Services(GMS),而FCM的核心推送能力完全依赖GMS运行,这就是你调用FirebaseInstanceId.getInstance().getToken()一直返回null的根本原因。下面给你两种可行的解决方案,优先推荐第一种,毕竟适配亚马逊自家的服务更稳定:
方案一:改用亚马逊官方的ADM(强烈推荐)
Kindle是亚马逊生态的亲儿子,ADM(Amazon Device Messaging)是专门为它打造的推送服务,完全不需要依赖GMS,兼容性和稳定性拉满。
具体操作步骤:
在亚马逊开发者后台注册应用:
登录亚马逊开发者控制台,创建你的应用,获取ADM所需的API密钥和凭据(这个步骤和注册FCM流程类似,跟着引导走就行)。集成ADM SDK到项目:
- 在项目的
build.gradle(Module级别)中添加依赖:dependencies { implementation 'com.amazon:adm:1.1.1' } - 在
AndroidManifest.xml里配置权限和服务:<!-- 声明ADM相关权限 --> <uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" /> <permission android:name="你的应用包名.permission.RECEIVE_ADM_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="你的应用包名.permission.RECEIVE_ADM_MESSAGE" /> <!-- 注册ADM消息处理服务 --> <service android:name=".ADMMessageReceiverService" android:exported="false"> <intent-filter> <action android:name="com.amazon.device.messaging.intent.RECEIVE" /> </intent-filter> </service> <service android:name=".ADMTokenRefreshService" android:exported="false"> <intent-filter> <action android:name="com.amazon.device.messaging.intent.REGISTRATION" /> </intent-filter> </service> <!-- 添加ADM元数据(可选,配置启动屏) --> <meta-data android:name="com.amazon.device.messaging.splashscreen" android:resource="@drawable/your_splash_icon" />
- 在项目的
实现ADM令牌获取逻辑:
创建两个服务类分别处理令牌刷新和消息接收:import com.amazon.device.messaging.ADM; import com.amazon.device.messaging.ADMMessageHandlerBase; import android.content.Intent; import android.util.Log; // 处理令牌刷新的服务 public class ADMTokenRefreshService extends ADMMessageHandlerBase { public ADMTokenRefreshService() { super(ADMTokenRefreshService.class.getName()); } @Override protected void onRegistered(String registrationId) { // 这里拿到的registrationId就是Kindle的推送令牌,直接存到你的服务器就行 saveTokenToServer(registrationId); } @Override protected void onUnregistered(String registrationId) { // 令牌失效时,从服务器移除该设备记录 removeTokenFromServer(registrationId); } @Override protected void onMessage(Intent intent) { // 处理收到的推送消息,和FCM的onMessageReceived逻辑类似 handlePushMessage(intent); } @Override protected void onRegistrationError(String errorId) { // 处理注册失败的情况,比如日志上报 Log.e("ADM", "Registration failed with error: " + errorId); } // 以下是你自己需要实现的业务方法 private void saveTokenToServer(String token) { /* 你的服务器存储逻辑 */ } private void removeTokenFromServer(String token) { /* 你的服务器移除逻辑 */ } private void handlePushMessage(Intent intent) { /* 你的消息处理逻辑 */ } }初始化ADM并请求令牌:
在应用启动的地方(比如Application类或主Activity的onCreate方法)添加:ADM adm = new ADM(getApplicationContext()); if (adm.isSupported()) { String existingToken = adm.getRegistrationId(); if (existingToken == null) { // 没有令牌,发起注册请求 adm.startRegister(); } else { // 已有令牌,直接使用 saveTokenToServer(existingToken); } } else { // 极少数情况:设备不支持ADM(比如非Kindle的亚马逊设备) Log.w("ADM", "ADM is not supported on this device"); }
方案二:尝试给Kindle安装GMS(不推荐,兼容性差)
如果你铁了心要用FCM,只能尝试给Kindle手动安装Google Play Services,但要提前做好心理准备:
- 不是所有Kindle型号都支持,旧型号硬件可能不兼容
- 安装过程需要用户手动解锁设备、刷入GMS包,门槛极高,普通用户很难操作
- 后续系统更新可能会直接干掉GMS,稳定性完全没保障
大致操作流程(仅作参考):
- 确认你的Kindle型号支持安装GMS(比如Kindle Fire HD 8/10 2018及以后的型号)
- 解锁设备的bootloader(部分型号需要,步骤比较繁琐)
- 下载对应型号的GMS安装包(注意版本要和设备系统版本匹配)
- 通过adb或Recovery模式刷入GMS包
- 安装完成后,登录Google Play商店,确认GMS正常运行
- 此时再调用FCM的令牌获取方法,大概率能拿到非null的结果
额外优化建议
如果你的应用需要同时支持普通Android/iOS和Kindle设备,可以在代码中做设备判断,自动切换推送服务:
public String getDevicePushToken(Context context) { String token = null; // 判断是否是亚马逊设备 if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) { // 使用ADM获取令牌 ADM adm = new ADM(context); token = adm.getRegistrationId(); } else { // 使用FCM获取令牌 token = FirebaseInstanceId.getInstance().getToken(); } return token; }
测试的时候一定要用真实的Kindle设备,模拟器很难模拟ADM或GMS的真实环境。
内容的提问来源于stack exchange,提问作者Carlos Daniel




