如何仅在特定活动触发后启动FCM ID服务?

问题描述:

假设我有一个LoginActivity用户可以注册或使用现有凭证登录。除非用户登录并且启动应用程序的MainActivity,否则我不希望FirebaseInstanceIdService生成令牌。如何仅在特定活动触发后启动FCM ID服务?

谢谢

+0

只要打电话给'FirebaseInstanceId.getInstance()。为gettoken()'在'MainActivity'的'的onCreate()'。或者在活动中的任何地方,您认为您需要它。 –

+0

根据日志,我的FirebaseInstanceIdService实现在应用程序启动时生成令牌。有什么办法可以防止这种情况发生? – Bravo

+0

对不起。我有点困惑。你是指'FirebaseInstanceIdService.onTokenRefresh()'? –

不能被调用,直到用户登录阻止FirebaseInstanceIdService.onTokenRefresh()

,你可以在你的使用情况做的是:

  • FirebaseInstanceIdService.onTokenRefresh()忽略如果事件用户未登录
  • 当用户登录检查FirebaseInstanceId.getToken()并且如果!= null调用onTokenRefresh()(或直接您的逻辑)ma nually。

通过这种方式,您可以在用户登录时处理令牌,并且如果令牌不可用(或旋转),稍后您将收到onTokenRefresh()事件。

更新(2017年7月3日):在评论读者提醒FirebaseInstanceIdService.onTokenRefresh()可以在用户登录后可以称为

这是正确的。如果用户登录,getToken()仍然可以返回null如果onTokenRefresh()以前未被调用过。

你需要在你的应用程序中处理这种情况。无论如何,用户最有可能使用该应用程序,但只有在收到令牌后才能发送推送通知。

当终于调用onTokenRefresh()时,如果用户之前登录过,则可以将令牌与用户关联起来。

+0

如果在用户登录后调用FirebaseInstanceIdService.onTokenRefresh()会发生异步调用,该怎么办? –

+0

这可能会发生,您需要在应用中处理这种情况。无论如何,用户最有可能使用该应用程序,但只有在收到令牌后才能发送推送通知。然后,当您收到令牌时,您可以将其与以前登录的用户相关联。 (我也更新了答案) –

+0

很好,但我认为我们需要在登录后删除实例并调用getInstance()方法,以防Firebase之前调用它从新生成的实例中获取新的令牌。 –

对不起,但这是不可能的。 FirebaseInstanceIdService在应用程序启动时自动调用并生成Token。请记住,它与应用程序Instance有关。不与一个特定的用户。如果你正试图保存Token与一个特定的用户(即当用户登录时,那么你将保存该服务器数据库token推送通知该用户)。如果你这样做,你将面临的错误是,如果两个用户共享一个应用程序Instance然后推送通知可能会被推送到错误的用户.. 希望你明白我的观点。

+2

嗨Usmal。如何解决这个问题呢?也许从我的服务器上的注销用户中删除令牌关联,并将其添加到新登录的用户......您怎么看? – Alessandro

+0

@Alessandro是的,我有一个问题..我做了你提到的 –

+0

谢谢你,我做同样的事情! :) – Alessandro

我在共享pref中维护一个标志,它指示gcm令牌是否发送到服务器。在每次我调用一个方法sendDevicetokenToServer时,在Splash屏幕中。此方法检查用户标识是否为空,然后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); 

}