FCM: onNewToken vs FirebaseInstanceId

2019-01-23 09:41发布

问题:

Firebase has deprecated some of the messaging calls in the com.google.firebase:firebase-messaging:17.1.0 release. This post goes over those changes nicely.

Question: Can someone tell me if is it considered bad practice to not implement onNewToken and instead just call the below block each app launch This probably seems excessive to Android folks but feels like home from an iOS point of view.

FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(this) { instanceIdResult ->
    // Just use this call 
    val newToken = instanceIdResult.token
    Log.i("newToken", newToken)
}



@Override
public void onNewToken(String s) {
    super.onNewToken(s);
    // Leave this unimplemented
}

I am more familiar with iOS which calls its onNewToken equivalent on every app launch. So for iOS I put logic there to determine if my backend needs to be updated.

getInstanceId() docs say This generates an Instance ID if it does not exist yet, which starts periodically sending information to the Firebase backend. This makes me assume I can just call FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener each launch.

回答1:

First of all, I'm highly skeptical of any logic that suggests that if something is OK in iOS, that it would be OK on Android!

The implementation of push messaging between Android and iOS is extremely different. On Android, it's dependent on Play Services, which runs in another process. On iOS, it's something completely different. The rules of engagement are simply not at all the same.

Note that the suggested token retrieval method is via callback. That is suggesting that token generation is essentially asynchronous. In other words, at app launch (in whatever way you actually define that), the background stuff that manages to token might not be done with that yet. There simply might not be any token available when you ask for it. And who knows how long that takes? You're better off just accepting the token when the system tells you it's ready instead of making a guess about when it's ready. Follow the recommended implementation path.



回答2:

Despite the documentation says that onNewToken is called upon the first app start, it is not. That is why I use FirebaseInstanceId respectively getToken() when I need the Id while onNewToken has not been called before although the app is already running for a while. (So we do both in our project)

What I observe is that Firebase will call onNewToken shortly after I was fetching the token via FirebaseInstanceId. It seems that fetching the token this way initiates something within the Firebase service.

However, it works that way and that is good enough for our current project.

Edit: As getToken() of FirebaseInstanceId got deprecated recently, please refer to Arthur Thompson's answer.



回答3:

Calling FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener on every app launch is an option (an unnecessary option), onNewToken is there specifically to provide you access to the token when available.

Note that calling FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener on every app launch would require you to handle the case when the token is not yet available, using onNewToken avoids that.



回答4:

The onNewToken() function works like it's predecessor, onTokenRefresh().

Implementing the first block on your post requests and waits for a token. This guarantees that a token (or an exception) would return. However, that token isn't guaranteed to stay the same forever. Similar with onTokenRefresh(), onNewToken() is triggered when a token for the corresponding app instance is generated, which in turn you should use and replace with the old token you got.

My answer here has more details.