【问题标题】:How to launch FCM ID Service only after a particular activity is triggered?如何仅在触发特定活动后启动 FCM ID 服务?
【发布时间】:2016-09-27 18:53:23
【问题描述】:

假设我有一个LoginActivity,用户可以在其中注册或使用现有凭据登录。我不希望FirebaseInstanceIdService 生成令牌,除非用户已登录并且应用程序的MainActivity 已启动。

谢谢

【问题讨论】:

  • 只需在您的MainActivityonCreate() 中调用FirebaseInstanceId.getInstance().getToken()。或者在 Activity 中您认为需要它的任何位置。
  • 根据日志,我的FirebaseInstanceIdService 实现会在应用程序启动时生成令牌。有什么办法可以防止这种情况发生吗?
  • 对不起。我有点困惑。你指的是FirebaseInstanceIdService.onTokenRefresh()吗?
  • 是的,很抱歉没有指出这一点
  • 嗯。当需要新的 InstanceId 时,onTokenRefresh() 将始终触发(之前的令牌已失效)。查看doc 了解触发此问题的原因。

标签: android google-cloud-messaging firebase-cloud-messaging


【解决方案1】:

在用户登录之前,您不能阻止 FirebaseInstanceIdService.onTokenRefresh() 被调用。

你可以在你的用例中做的是:

  • FirebaseInstanceIdService.onTokenRefresh() 中,如果用户未登录则忽略该事件
  • 当用户登录时检查FirebaseInstanceId.getToken(),如果!= null 手动调用onTokenRefresh()(或直接调用您的逻辑)。

通过这种方式,您可以在用户登录时处理令牌,如果令牌不可用(或被轮换),您稍后会收到onTokenRefresh() 事件。

更新(2017 年 7 月 3 日):在 cmets 中,一位读者提醒,FirebaseInstanceIdService.onTokenRefresh() 可以在用户登录后调用。

这是对的。当用户登录时,如果onTokenRefresh()之前没有被调用,getToken()仍然可以返回null

您需要在您的应用中处理这种情况。用户很可能仍然可以使用该应用程序,但在收到令牌之前您无法发送推送通知。

onTokenRefresh()最终被调用时,如果用户之前登录过,则可以将令牌关联到用户。

【讨论】:

  • 如果用户登录后调用 FirebaseInstanceIdService.onTokenRefresh() 是异步调用怎么办?
  • 这可能会发生,您需要在您的应用程序中处理这种情况。用户很可能仍然可以使用该应用程序,但在收到令牌之前您无法发送推送通知。然后,当您收到令牌时,您可以将其与之前登录的用户相关联。 (我也更新了答案)
  • 很好,但我认为我们需要删除实例并在登录后调用 getInstance() 方法,以防它之前被 firebase 调用以从新生成的实例中获取新令牌。
  • 不需要
【解决方案2】:

抱歉,这是不可能的。 FirebaseInstanceIdService 在应用程序启动时自动调用并生成Token。请记住,它与应用程序 Instance 相关。不是针对某个特定用户。如果您尝试使用某个特定用户保存Token(即,当用户登录时,您将在服务器数据库中保存token 以获取该用户的推送通知)。如果您这样做,您将在未来面临一个错误是如果 两个 用户共享一个应用程序Instance 则推送通知可能会推送给错误的用户.. 希望你明白我的意思。

【讨论】:

  • 嗨,乌斯马尔。如何解决这个问题呢?也许从我的服务器上的已注销用户中删除令牌关联,并将其添加到新登录的用户......你怎么看?
  • @Alessandro 是的,我遇到了问题..我做了你提到的事情
  • 谢谢,我也在做同样的事情! :)
  • @usmanlqbal 我有一个问题..我想在初始屏幕上获取 fcm id..但问题是我的另一个 api 先调用然后我得到 fcm id..有什么问题
  • @AdityaVyas-Lakhan 您需要在 FCMservice 方法中进行 api 调用onTokenRefresh()
【解决方案3】:

我在共享首选项中维护一个标志,指示是否将 gcm 令牌发送到服务器。每次我调用一种方法 sendDevicetokenToServer 时,在启动画面中。此方法检查用户 id 是否为空并且 gcm 发送状态然后将令牌发送到服务器。

   public static void  sendRegistrationToServer(final Context context) {

    if(Common.getBooleanPerf(context,Constants.isTokenSentToServer,false) ||
            Common.getStringPref(context,Constants.userId,"").isEmpty()){

        return;
    }

    String token =  FirebaseInstanceId.getInstance().getToken();
    String userId = Common.getUserId(context);
    if(!userId.isEmpty()) {
        HashMap<String, Object> reqJson = new HashMap<>();
        reqJson.put("deviceToken", token);
        ApiInterface apiService =
                ApiClient.getClient().create(ApiInterface.class);

        Call<JsonElement> call = apiService.updateDeviceToken(reqJson,Common.getUserId(context),Common.getAccessToken(context));
        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> serverResponse) {

                try {
                    JsonElement jsonElement = serverResponse.body();
                    JSONObject response = new JSONObject(jsonElement.toString());
                    if(context == null ){
                        return;
                    }
                    if(response.getString(Constants.statusCode).equalsIgnoreCase(Constants.responseStatusSuccess)) {

                        Common.saveBooleanPref(context,Constants.isTokenSentToServer,true);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable throwable) {

                Log.d("", "RetroFit2.0 :getAppVersion: " + "eroorrrrrrrrrrrr");
                Log.e("eroooooooorr", throwable.toString());
            }
        });

    }

}

在 MyFirebaseInstanceIDService 类中

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

    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // Instance ID token to your app server.
    Common.saveBooleanPref(this,Constants.isTokenSentToServer,false);
    Common.sendRegistrationToServer(this);

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 2022-12-03
    • 1970-01-01
    相关资源
    最近更新 更多