如何仅在触发特定 activity 后启动 FCM ID 服务?
How to launch FCM ID Service only after a particular activity is triggered?
假设我有一个 LoginActivity
,用户可以在其中注册或使用现有凭据登录。我不希望 FirebaseInstanceIdService
生成令牌,除非用户已登录并且应用程序的 MainActivity
已启动。
谢谢
在用户登录之前,您不能阻止 FirebaseInstanceIdService.onTokenRefresh()
被调用。
在您的用例中您可以做的是:
- 在
FirebaseInstanceIdService.onTokenRefresh()
中,如果用户未登录则忽略该事件
- 当用户登录时检查
FirebaseInstanceId.getToken()
如果 != null
手动调用 onTokenRefresh()
(或直接你的逻辑)。
通过这种方式,您可以在用户登录时处理令牌,如果令牌不可用(或轮换),您稍后将收到 onTokenRefresh()
事件。
更新(2017年7月3日):评论中有reader提示用户登录后可以调用FirebaseInstanceIdService.onTokenRefresh()
没错。当用户登录时,如果之前没有调用 onTokenRefresh()
,getToken()
仍然可以 return null
。
您需要在您的应用中处理这种情况。用户很可能无论如何都可以使用该应用程序,但是在您收到令牌之前您无法发送推送通知。
最终调用onTokenRefresh()
时,如果用户之前登录过,那么您可以将令牌关联到用户。
抱歉,这是不可能的。 FirebaseInstanceIdService
在应用程序启动时自动调用并生成 Token
。请记住,它与应用程序 Instance
相关。不是与一个特定的用户。如果你试图用一个特定的用户保存 Token
(即当用户登录时,你将把 token
保存在服务器数据库中以用于该用户的推送通知)。如果你这样做是一个错误,你将来会面临的是,如果 两个 用户共享一个应用程序 Instance
那么推送通知可能会被推送给错误的用户..
希望你明白我的意思。
我在 shared pref 中维护一个标志,它指示 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 中 class
@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);
}
假设我有一个 LoginActivity
,用户可以在其中注册或使用现有凭据登录。我不希望 FirebaseInstanceIdService
生成令牌,除非用户已登录并且应用程序的 MainActivity
已启动。
谢谢
在用户登录之前,您不能阻止 FirebaseInstanceIdService.onTokenRefresh()
被调用。
在您的用例中您可以做的是:
- 在
FirebaseInstanceIdService.onTokenRefresh()
中,如果用户未登录则忽略该事件 - 当用户登录时检查
FirebaseInstanceId.getToken()
如果!= null
手动调用onTokenRefresh()
(或直接你的逻辑)。
通过这种方式,您可以在用户登录时处理令牌,如果令牌不可用(或轮换),您稍后将收到 onTokenRefresh()
事件。
更新(2017年7月3日):评论中有reader提示用户登录后可以调用FirebaseInstanceIdService.onTokenRefresh()
没错。当用户登录时,如果之前没有调用 onTokenRefresh()
,getToken()
仍然可以 return null
。
您需要在您的应用中处理这种情况。用户很可能无论如何都可以使用该应用程序,但是在您收到令牌之前您无法发送推送通知。
最终调用onTokenRefresh()
时,如果用户之前登录过,那么您可以将令牌关联到用户。
抱歉,这是不可能的。 FirebaseInstanceIdService
在应用程序启动时自动调用并生成 Token
。请记住,它与应用程序 Instance
相关。不是与一个特定的用户。如果你试图用一个特定的用户保存 Token
(即当用户登录时,你将把 token
保存在服务器数据库中以用于该用户的推送通知)。如果你这样做是一个错误,你将来会面临的是,如果 两个 用户共享一个应用程序 Instance
那么推送通知可能会被推送给错误的用户..
希望你明白我的意思。
我在 shared pref 中维护一个标志,它指示 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 中 class
@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);
}