start method
Turn-key enable: permission → token → register → refresh + open handlers.
Called automatically when pushEnabled is set. Safe to call again; every
failure is caught and logged so push can never break the app.
Implementation
Future<void> start() async {
try {
final platform = _detectPlatform();
if (platform == null) {
NexusLog.info('push: platform not supported for FCM — skipping');
return;
}
if (!await _ensureFirebase(platform)) return;
final messaging = FirebaseMessaging.instance;
if (_cfg.pushAutoRequestPermission) {
final settings = await messaging.requestPermission();
NexusLog.debug('push: permission ${settings.authorizationStatus.name}');
}
// FCM does not draw a notification while the app is foregrounded — show it
// ourselves so notifications appear whether the app is open or not.
if (_cfg.pushForegroundDisplay) await _setupForegroundDisplay(platform, messaging);
// Android: campaigns arrive as data messages so the SDK renders every
// notification natively (foreground AND background/killed) with full
// options + action buttons. Register the background renderer.
if (platform == PushPlatform.android && _cfg.pushForegroundDisplay) {
// Single shared background handler — see ensureNexusBackgroundHandler.
// (Registering nexusPushBackgroundHandler directly would clobber Voice.)
ensureNexusBackgroundHandler();
}
final token = platform == PushPlatform.web
? await messaging.getToken(vapidKey: _cfg.pushWebVapidKey)
: await messaging.getToken();
if (token != null) {
await registerToken(token, platform: platform, provider: PushProvider.fcm);
}
await _refreshSub?.cancel();
_refreshSub = messaging.onTokenRefresh.listen(
(t) => registerToken(t, platform: platform, provider: PushProvider.fcm),
);
// Attribute the open that launched / foregrounded the app.
final initial = await messaging.getInitialMessage();
if (initial != null) await reportOpen(initial.data);
await _openSub?.cancel();
_openSub = FirebaseMessaging.onMessageOpenedApp.listen((m) => reportOpen(m.data));
NexusLog.info('push: enabled (${platform.name})');
} catch (e) {
NexusLog.warn('push: start failed — $e');
}
}