mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Initialize Firebase at startup so iOS APNs token is captured
Firebase was only initialized lazily when the user toggled push on. On iOS the firebase_messaging plugin installs its APNs swizzling at app launch, but the delivered device token can only be forwarded to FCM if a FirebaseApp is already configured at that point. With lazy init there was none, so getAPNSToken() never resolved and enabling push failed with "Could not enable push". Add initFirebaseForPush() (mobile-only, idempotent) and call it from main() at launch. Extract a shared pushSupportedOnThisPlatform getter so isSupported and the initializer stay in sync; _ensureFirebase() now delegates to it as a safety net. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7d7f0197cd
commit
3d190e847e
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:frontend/theme/catppuccin_mocha_theme.dart';
|
import 'package:frontend/theme/catppuccin_mocha_theme.dart';
|
||||||
import 'package:frontend/utils/local_network_permission.dart';
|
import 'package:frontend/utils/local_network_permission.dart';
|
||||||
import 'package:frontend/utils/pref_utils.dart';
|
import 'package:frontend/utils/pref_utils.dart';
|
||||||
|
import 'package:frontend/utils/push_service.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'navigation.dart';
|
import 'navigation.dart';
|
||||||
import 'theme/gruvbox_theme.dart';
|
import 'theme/gruvbox_theme.dart';
|
||||||
@@ -31,6 +32,15 @@ void main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize Firebase at launch so the firebase_messaging plugin's iOS
|
||||||
|
// APNs swizzling has a configured app to forward the device token to;
|
||||||
|
// without this getAPNSToken() never resolves and enabling push fails.
|
||||||
|
try {
|
||||||
|
await initFirebaseForPush();
|
||||||
|
} catch (e, stack) {
|
||||||
|
debugPrint('Firebase init for push failed, continuing: $e\n$stack');
|
||||||
|
}
|
||||||
|
|
||||||
// Settle iOS's local-network permission now, at launch, so it isn't
|
// Settle iOS's local-network permission now, at launch, so it isn't
|
||||||
// still being decided when the user first taps "Test" in settings.
|
// still being decided when the user first taps "Test" in settings.
|
||||||
unawaited(requestLocalNetworkPermission());
|
unawaited(requestLocalNetworkPermission());
|
||||||
|
|||||||
@@ -6,6 +6,25 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|||||||
import '../firebase_options.dart';
|
import '../firebase_options.dart';
|
||||||
import 'oott_api.dart';
|
import 'oott_api.dart';
|
||||||
|
|
||||||
|
/// Whether push is available on this platform/build (mobile only — FCM/APNs).
|
||||||
|
/// Shared by [FirebasePushService.isSupported] and [initFirebaseForPush] so the
|
||||||
|
/// two never drift.
|
||||||
|
bool get pushSupportedOnThisPlatform =>
|
||||||
|
!kIsWeb &&
|
||||||
|
(defaultTargetPlatform == TargetPlatform.android ||
|
||||||
|
defaultTargetPlatform == TargetPlatform.iOS);
|
||||||
|
|
||||||
|
/// Initializes Firebase at app startup on push-capable platforms. This must run
|
||||||
|
/// at launch — the firebase_messaging plugin wires up iOS APNs swizzling in the
|
||||||
|
/// AppDelegate at launch, and it can only forward the APNs device token to FCM
|
||||||
|
/// if a FirebaseApp is already configured when iOS delivers it. Without this,
|
||||||
|
/// `getAPNSToken()` never resolves and enabling push fails. No-op on web/desktop
|
||||||
|
/// and if Firebase is already initialized.
|
||||||
|
Future<void> initFirebaseForPush() async {
|
||||||
|
if (!pushSupportedOnThisPlatform || Firebase.apps.isNotEmpty) return;
|
||||||
|
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||||
|
}
|
||||||
|
|
||||||
/// Per-device push enable/disable, behind an interface so the settings UI can be
|
/// Per-device push enable/disable, behind an interface so the settings UI can be
|
||||||
/// driven by a fake in tests without pulling in Firebase. Tapping a push only
|
/// driven by a fake in tests without pulling in Firebase. Tapping a push only
|
||||||
/// opens the app (no deep-link, no identifier); the in-app notification list
|
/// opens the app (no deep-link, no identifier); the in-app notification list
|
||||||
@@ -47,24 +66,16 @@ class FirebasePushService implements PushService {
|
|||||||
bool _foregroundDisplayWired = false;
|
bool _foregroundDisplayWired = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get isSupported =>
|
bool get isSupported => pushSupportedOnThisPlatform;
|
||||||
!kIsWeb &&
|
|
||||||
(defaultTargetPlatform == TargetPlatform.android ||
|
|
||||||
defaultTargetPlatform == TargetPlatform.iOS);
|
|
||||||
|
|
||||||
String get _platformName =>
|
String get _platformName =>
|
||||||
defaultTargetPlatform == TargetPlatform.iOS ? 'ios' : 'android';
|
defaultTargetPlatform == TargetPlatform.iOS ? 'ios' : 'android';
|
||||||
|
|
||||||
Future<void> _ensureFirebase() async {
|
// Safety net in case startup init was skipped; normally Firebase is already
|
||||||
// Options come from the committed firebase_options.dart rather than native
|
// initialized at launch by initFirebaseForPush(). Options come from the
|
||||||
// config files, so no google-services.json / GoogleService-Info.plist is
|
// committed firebase_options.dart rather than native config files, so no
|
||||||
// needed in the build.
|
// google-services.json / GoogleService-Info.plist is needed in the build.
|
||||||
if (Firebase.apps.isEmpty) {
|
Future<void> _ensureFirebase() => initFirebaseForPush();
|
||||||
await Firebase.initializeApp(
|
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> enable() async {
|
Future<bool> enable() async {
|
||||||
|
|||||||
Reference in New Issue
Block a user