FCM + AppIcon 2

This commit is contained in:
2026-03-21 13:27:11 -05:00
parent 34d7d9e783
commit d7302856dc
24 changed files with 84 additions and 23 deletions

View File

@@ -1,18 +1,50 @@
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
class FcmService {
/// Request permission, fetch the FCM token, and register it with the server.
/// Safe to call on every login/session-restore — the server just upserts the value.
static Future<void> register() async {
debugPrint('FCM: register() called');
try {
final messaging = FirebaseMessaging.instance;
await messaging.requestPermission(alert: true, badge: true, sound: true);
final settings = await messaging.requestPermission(alert: true, badge: true, sound: true);
debugPrint('FCM: authorization status: ${settings.authorizationStatus}');
if (settings.authorizationStatus == AuthorizationStatus.denied) {
debugPrint('FCM: notifications denied — enable in Settings > [App] > Notifications');
return;
}
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
// On iOS, APNs token must be available before FCM token can be fetched.
// getAPNSToken() can block if iOS hasn't finished APNs registration yet,
// so cap it with a timeout and retry once after a short delay.
if (defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.macOS) {
String? apnsToken = await messaging.getAPNSToken()
.timeout(const Duration(seconds: 3), onTimeout: () => null);
if (apnsToken == null) {
debugPrint('FCM: APNs token not ready, retrying in 5s...');
await Future.delayed(const Duration(seconds: 5));
apnsToken = await messaging.getAPNSToken()
.timeout(const Duration(seconds: 5), onTimeout: () => null);
}
if (apnsToken == null) {
debugPrint('FCM: APNs token unavailable — simulator or APNs not configured');
return;
}
debugPrint('FCM: APNs token acquired');
}
final token = await messaging.getToken();
debugPrint('FCM TOKEN: ${token ?? "null — likely running on simulator"}');
if (token == null) return;
await securePost({'token': token}, 'register_fcm_token');
} catch (_) {
// Non-fatal — push notifications simply won't work until the next successful registration.
} catch (e) {
debugPrint('FCM registration failed: $e');
}
}
}

View File

@@ -59,21 +59,21 @@ class DefaultFirebaseOptions {
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyC0MWniqI8flETaT8zKwXQzBhYRljKIKvk',
appId: '1:956683546941:ios:162a6b8aa58f1eb8121554',
apiKey: 'AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo',
appId: '1:956683546941:ios:1059be0ae683894b121554',
messagingSenderId: '956683546941',
projectId: 'blindmaster-54055',
storageBucket: 'blindmaster-54055.firebasestorage.app',
iosBundleId: 'com.example.blindMaster',
iosBundleId: 'com.adipu.blindMaster',
);
static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyC0MWniqI8flETaT8zKwXQzBhYRljKIKvk',
appId: '1:956683546941:ios:162a6b8aa58f1eb8121554',
apiKey: 'AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo',
appId: '1:956683546941:ios:1059be0ae683894b121554',
messagingSenderId: '956683546941',
projectId: 'blindmaster-54055',
storageBucket: 'blindmaster-54055.firebasestorage.app',
iosBundleId: 'com.example.blindMaster',
iosBundleId: 'com.adipu.blindMaster',
);
static const FirebaseOptions windows = FirebaseOptions(

View File

@@ -1,3 +1,4 @@
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
import 'package:blind_master/BlindMasterScreens/Startup/splash_screen.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -16,6 +17,7 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
FirebaseMessaging.instance.onTokenRefresh.listen((_) => FcmService.register());
runApp(const MyApp());
}