如何处理 FirebaseInstanceId.getInstance().getToken() = null?

15

我刚刚迁移到 FCM。我已经添加了一个继承自 FirebaseInstanceIdService 的类,以在适当时接收刷新的令牌。

我的问题是针对用户第一次安装应用程序并由于某种原因无法从 onTokenRefresh 中接收到注册 ID 的情况。我们该如何处理这种情况?我能否从我的 FirebaseInstanceIdService 类中设置广播接收器,在接收到注册 ID 时通知主 Activity?


是的,那么如何处理这个问题? - Lucky
谢谢@ChintanSoni。我会试一下! - Lucky
1
似乎FCM在像小米这样的带有中国操作系统版本的设备上不完全功能(它没有GooglePlay服务,但即使安装了GPServices后仍然不完全功能)。 - Vitaliy A
@VitaliyA 在Nexus 5x上遇到了同样的问题...不是中国版的操作系统.... -_- - Rahim Rahimov
@VitaliyA 同样的问题。在小米手机上无法获取注册令牌,但在模拟器、摩托罗拉和三星手机上可以。你有没有想到解决办法? - Manisha
显示剩余4条评论
7个回答

18
  • 如果您的设备没有连接到互联网,则onTokenRefresh()不会被调用,您应该通知用户他/她的设备没有互联网连接。
  • firebase有自己的网络变化监听器,当设备连接到互联网时,尝试获取令牌并返回它,此时您可以通过发送本地广播接收器告诉您的主要活动已接收到注册令牌。

请使用以下代码:

    @Override
public void onTokenRefresh() {

    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();

    Log.d("FCN TOKEN GET", "Refreshed token: " + refreshedToken);

    final Intent intent = new Intent("tokenReceiver");
    // You can also include some extra data.
    final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
    intent.putExtra("token",refreshedToken);
    broadcastManager.sendBroadcast(intent);


}

在你的主活动中:

    public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
   LocalBroadcastManager.getInstance(this).registerReceiver(tokenReceiver,
            new IntentFilter("tokenReceiver"));

}

BroadcastReceiver tokenReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String token = intent.getStringExtra("token");
        if(token != null)
        {
            //send token to your server or what you want to do
        }

    }
};

}

2
嗨,我想知道如果没有令牌该怎么办。在我的应用程序中,一开始就必须有一个令牌。我在想它可能会像这样进行:启动屏幕-> 如果(没有令牌){继续使用启动屏幕,直到获得令牌,然后将启动屏幕删除以进入主活动}。任何帮助都将不胜感激。 - Wisd0m
当您的应用程序启动FirebaseInstanceId服务时,请尝试从FCM获取令牌,您可以在启动屏幕中显示进度条,直到FirebaseInstanceId服务返回令牌。如果FirebaseInstanceId返回令牌,则将其发送到您的应用程序服务器,并告诉您的启动屏幕活动已收到令牌,使用LocalBroadcastManager关闭启动屏幕并显示您的应用程序主活动。否则,请告诉启动屏幕活动无法接收令牌,并向用户显示消息,表示您没有互联网连接。用户连接到互联网后,FirebaseInstanceId服务会再次尝试获取令牌。 - Edalat Feizi
谢谢您的回复,我会尝试实现它。还有一件事,如果您能帮助我理解,我的Android应用程序是用PHP开发的,并显示为webView。我可以将令牌发送到服务器,但是如何在我的PHP服务器上存储令牌以在用户注册时使用,以便我可以将令牌和用户ID存储在数据库中?任何帮助都将不胜感激,因为我已经卡在这个问题上4天了。 - Wisd0m
美丽的,谢谢。 - Alaa
@Alaa 很高兴能帮助你 :) - Edalat Feizi

12

将manifest.xml文件中的 tools:node="replace" 替换为 tools:node="merge"。


6
据我所知,只有在你尝试在没有安装 Google Play 服务的模拟器上运行应用程序时,并且在您的实际设备上使用双重电子邮件 ID(但仅验证了一个电子邮件 ID),才会出现 token 为空的情况。这些是会导致您获得空令牌的情况,而我已经在我的新项目中实现了 FCM。因此,在其他任何情况下,令牌都不会为空。请注意,保留 HTML 标记。

令牌在应用程序能够获取有效令牌之前将为null。 获取令牌的要求是:1.设备上安装了Google Play服务,2.设备已连接到互联网。 即使满足要求,令牌也可能需要一些时间(通常<10秒)才能可用。这取决于本地条件,如网络、设备负载等。 - Diego Giorgini
如果有延迟,将自动调用onTokenRefresh方法并获取更新的令牌;如果没有网络连接,则首先在应用中处理“互联网连接性”。 - Mrugesh

2
使用这个类来扩展...
public class MyFirebaseInstanceIDService  extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";
    public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";


    @Override
    public void onTokenRefresh() {
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        Toast.makeText(MyFirebaseInstanceIDService.this,refreshedToken,Toast.LENGTH_LONG).show();
    }
}

2

我曾经遇到过同样的问题。我查看了很多Stack Overflow帖子和其他论坛,最终找到了适合我的解决方案。FCM文档建议使用此方法获取令牌。

String refreshedToken = FirebaseInstanceId.getInstance().getToken();

我在网上找到了一篇帖子(抱歉,我不记得是哪一篇了。我很久以前就找到了),该帖子使用了以下方法:
String refreshedToken = FirebaseInstanceId.getInstance().getToken() (String authorizedEntity, String scope);

FCM文档将第一种方法描述为:

返回默认Firebase项目的主令牌。

而第二种方法被描述为:

返回一个令牌,该令牌授权实体代表由Instance ID标识的应用程序执行操作。 这类似于OAuth2令牌,但它适用于应用程序实例而不是用户。 例如,要获取可用于通过FirebaseMessaging发送消息到应用程序的令牌,请设置为发送者ID,并将其设置为“FCM”。

我一直在研究为什么第一种方法调用需要更长时间才能返回令牌,但我还没有找到答案。希望这可以帮助您。


4
这应该是一条评论,而不是一个答案。如果这是一个重复的问题,投票关闭 或者 标记 为重复,并/或者在你获得足够的声望后留下评论。如果不是,那么请根据这个特定的问题来回答。 - NobodyNada
@NobodyNada 你本可以直接说出来,没有必要对一个可行的答案进行负评。 - Marline
2
很抱歉,这不是“可行的答案”。请参见你的答案在另一个城堡里;什么样的回答不算是回答? - NobodyNada
我已经在这个问题上提出了重复标记。它们看起来确实是相同的。同时,建议您删除此答案并自行标记为重复;它没有增加价值,反而会引起负面注意。 - Krease
1
@Krease 我没有足够的声望来标记这个问题为重复,既不是在你的投票之前也不是之后。我根据自己的知识调整了我的答案。希望现在它的格式可以被接受作为一个答案。 - Marline
我在FirebaseInstanceIdService的onTokenRefresh()中总是得到null令牌(第一次安装,其他启动,网络开/关等)。我尝试了所有方法,并通过切换到@Marline提到的重载public String getToken(String authorizedEntity,String scope)来获取令牌。 - Xaren

1
根据您的应用逻辑,您可以直接在FirebaseInstanceIdService.onTokenRefresh()方法中编写处理“new”标记的代码,或者如果需要在此事件发生时更改UI,则可以使用LocalBroadcast将此信息发送到您的活动。请注意,在调用onTokenRefresh()时,您的活动可能已经关闭。一种可能的实现方法是两个选项的混合:
  1. onTokenRefresh()中添加一些逻辑以将令牌发送到您的服务器
  2. 如果有需要在令牌可用时更改的UI组件,则使用LocalBroadcastReceiver通知您的活动。

0

如果您在模拟器上运行它,请检查您是否在“工具” -> “Android” -> “SDK 管理器” -> “SDK 工具” -> “Google Play 服务”中启用了 Google Play 服务。

安装完成后,请重新启动 Android Studio 和模拟器

这对我起作用了


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接