【问题标题】:Properly handling when FirebaseInstanceId.getInstance().getToken() is null当 FirebaseInstanceId.getInstance().getToken() 为空时正确处理
【发布时间】:2018-03-14 19:54:13
【问题描述】:

什么是让getToken() 以令牌 ID 返回的正确、可靠方式?

我见过几次尝试使用

  • while 循环,调用 getToken() 直到它不为空
  • 本地广播接收器
  • 定时器

while 循环似乎真的在 ANR 方面存在风险,并且循环无限期运行。

本地 BroadcastReceiver 并不适用于我的应用程序,因为即使我的应用程序中有一个主要活动,也没有任何东西强迫用户与之交互。用户可以在应用中完成任务,而无需通过该主要活动。

计时器看起来很脆弱。您需要等待多长时间?秒、分、小时?

Firebase 快速入门示例代码没有提供一个示例来处理getToken() 为空时的情况,而且我看不出有什么正确和可靠的实现可以确保返回一个令牌,没有上述实现的任何令人讨厌的副作用都会带来。

有一个回调方法可以挂钩,这不会成为问题,但由于它不可用,我只需要通过 StackOverflow 运行它,以了解人们如何解决这个问题。

注意:我已经实现了onTokenRefresh(),它适用于文档中所述的特定情况,但我不能单独使用,因为该应用只是升级 em> 在很多设备上,并且在应用升级期间不会调用此方法。我在 (Nexus) 硬件设备上有 null 问题,我根本没有使用模拟器,也不打算使用它。

【问题讨论】:

  • 在我的情况下,我每次启动应用程序时都会检查令牌并将其发送到服务器(如果服务器没有令牌)。
  • 当 APK 被替换为较新版本(“应用升级”)时,您是否看到令牌更改?这不是导致令牌更改的events listed in the docs 之一。
  • @wonsuc 正如我在问题中所说,getToken() 在随机情况下为空,因此它不可靠。我需要它保持一致。
  • @BobSnyder 我编辑了我的问题以澄清;升级应用程序时不会发生令牌更改,因此 onTokenRefresh 仅部分支持我的用例。我需要让 getToken() 可靠地返回一个令牌,但正如 API 中定义的那样,如果你能得到一个令牌,那就是抛硬币,因为“它可能还没有准备好”。而且无法知道它什么时候准备好
  • 到目前为止,我已经进行了调整以利用 FirebaseInstanceId.getInstance().deleteInstanceId();和 FirebaseInstanceId.getInstance().getToken();它以一种我一点都不满意的方式完成,除了它始终如一地工作;如果我没有本地存储 FCM 令牌 ID 的应用程序,我会调用 deleteInstanceId() 和 getToken() 来“强制”调用 onTokenrefresh()。我宁愿根本不必这样做,因为这感觉就像一个黑客。我将把这个问题保持一段时间,看看是否会出现其他更理智的问题。

标签: android firebase firebase-cloud-messaging


【解决方案1】:

除了我之前提到的方法之外,似乎没有人添加其他方法,我现在要回答我自己的问题。

我为生成令牌而实施的“解决方案”,以便您可以更一致地处理它,并将其存储以供以后参考,是这样的;

以下课程几乎完全按照快速入门进行。但是,我没有将令牌发送到服务器,而是在可以访问的确切时间将其存储起来以备后用:

public class FirebaseIdService extends FirebaseInstanceIdService {

@Override
public void onTokenRefresh() {
    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    if(refreshedToken != null) {
        Log.d("TOKENTAG", "Refreshed token: " + refreshedToken);
        SharedPreferences prefs = getApplicationContext().getSharedPreferences("pref_id", 0);
        prefs.edit().putString("share_pref_token", refreshedToken).apply();
    }
}

}

当我想要/需要发送令牌时,我会检查 SharedPreferences 中是否已有可用的令牌,如果没有,我只需删除 Firebase 实例并调用 getToken() 以生成另一个令牌。这本质上是告诉 Firebase“我想使当前实例无效”,然后通过调用 getToken() 之后,让它生成一个新实例,基本上使 onTokenRefresh() 被调用,每当令牌 已生成并且可用:

SharedPreferences prefs = getApplicationContext().getSharedPreferences("pref_id", 0);
if(prefs.getString("share_pref_token", "").isEmpty()) {
    Log.d("TOKENTAG", "token not available, so let's force one to be generated");
    try {
        FirebaseInstanceId.getInstance().deleteInstanceId();
    } catch (IOException e) {
        e.printStackTrace();
    }
    FirebaseInstanceId.getInstance().getToken();
}

我很确定这是一个次优的解决方案,我欢迎提出更好的建议,但在这一点上,这基本上是涵盖结合 onTokenRefresh() 和 @987654327 基础的唯一方法@ 更一致地获得一个没有任何上述缺点的令牌。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 2018-05-10
    相关资源
    最近更新 更多