Got APNs Device Token even before the app launches
the APNs device token is printed even before the initState method.
debug console:
...
Xcode build done. 13.4s
(lldb) 2023-05-17 18:44:02.304860+0800 Runner[41331:40367550] [SceneConfiguration] Info.plist contained no UIScene configuration dictionary (looking for configuration named "(no name)")
Warning: Unable to create restoration in progress marker file
+APNs Device Token: 85a621db04b45694ea6c04b8ace5668cde4e9cb922ae9e4198dd432cbd95354b
Connecting to VM Service at ws://127.0.0.1:50044/wwXLk8SuYmo=/ws
+flutter: initState
...
and Push.instance.onNewToken.listen is never get executed.
main.dart:
class _MyHomePageState extends State<MyHomePage> {
StreamSubscription<String>? onNewTokenSubscription;
@override
void initState() {
print("initState");
super.initState();
onNewTokenSubscription = Push.instance.onNewToken.listen((token) {
- print("Just got a new push notification registration token: ${token}");
});
}
@override
void dispose() {
onNewTokenSubscription?.cancel();
super.dispose();
}
void afterUserLogin() async {
final isGranted = await Push.instance.requestPermission();
}
...
still couldn't get onNewToken to work, workaround
final token = await Push.instance.token;
Hey @kukat, this probably happens because your app receives the APNs token before your that widget builds, and that time, listener in that widget hasn't been set up yet? You can either:
- keep using the
Push.instance.token(not a bad idea / hack / workaround, that's exactly what it's there for :) ) - move your
Push.instance.onNewToken.listento higher up in the widget tree so that it is built when the app first starts, or into a service that initializes when the app starts.
Push.instance.onNewToken.listen is useful to check if it has changed, so you can update your servers of the new token.
Let me know if that makes sense. Sorry for the late reply, I've been a bit busy 🙏
Ahh, @kukat I just looked at this again and found in the docs:
// To be informed that the device's token has been updated by the operating system
// You should update your servers with this token
Push.instance.onNewToken.listen((token) {
print("Just got a new FCM registration token: ${token}");
});
This doesn't include the first one. Not very intuitive, but this means whenever that is called, you should call your backend APIs to update the token. Otherwise this function would be called everytime the app is started.
I thought of a couple of approaches:
1. Minimal calls to onNewToken:
- Token is renewed, and
- app is first started (not when it is started for 2nd time, 3rd time or later). This would be unintuitive since when developers first use a library, they might not write production code (listens but doesn't ), the app might not registered properly so the
onNewTokenwas not called. This would involve persisting the token or flag that it is the first time the token was received.
Frequently call onNewToken. Whenever:
- Token is renewed, and
- whenever the app is started. Developers would need to decide if they should update their backend with the same token or not, or just do it everytime. An extra network request, but more intuitive.
What do you think?
Turns out Android does approach 1, so I will use the same to be consistent.