FCM + AppIcon 2
@@ -15,7 +15,7 @@
|
|||||||
"oauth_client": [],
|
"oauth_client": [],
|
||||||
"api_key": [
|
"api_key": [
|
||||||
{
|
{
|
||||||
"current_key": "AIzaSyBJzL-jeo4xa_rQkHymzku_2lIJ6WJ8hoI"
|
"current_key": "AIzaSyBC4WTj3CtJOJL1QSxrxrmjUEp1SSKHKzs"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"services": {
|
"services": {
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
8625E4152F6E711300C953BC /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
86D2D4E2E379E6C7A77A04E3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
86D2D4E2E379E6C7A77A04E3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
@@ -133,6 +134,7 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
8625E4152F6E711300C953BC /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
@@ -164,7 +166,6 @@
|
|||||||
A43606B2521A3B50E340351F /* Pods-RunnerTests.release.xcconfig */,
|
A43606B2521A3B50E340351F /* Pods-RunnerTests.release.xcconfig */,
|
||||||
97606C416DE8FC726A943531 /* Pods-RunnerTests.profile.xcconfig */,
|
97606C416DE8FC726A943531 /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -493,17 +494,20 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = YK2DB9NT3S;
|
DEVELOPMENT_TEAM = YK2DB9NT3S;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = BlindMaster;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.blindMaster;
|
PRODUCT_BUNDLE_IDENTIFIER = com.adipu.blindMaster;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -681,17 +685,20 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = YK2DB9NT3S;
|
DEVELOPMENT_TEAM = YK2DB9NT3S;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = BlindMaster;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.blindMaster;
|
PRODUCT_BUNDLE_IDENTIFIER = com.adipu.blindMaster;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -707,17 +714,20 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = YK2DB9NT3S;
|
DEVELOPMENT_TEAM = YK2DB9NT3S;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = BlindMaster;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.blindMaster;
|
PRODUCT_BUNDLE_IDENTIFIER = com.adipu.blindMaster;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import Flutter
|
import Flutter
|
||||||
|
import Firebase
|
||||||
|
import FirebaseMessaging
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@@ -7,10 +9,24 @@ import UIKit
|
|||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
// Explicitly register for remote notifications on every launch so iOS always
|
||||||
|
// calls didRegisterForRemoteNotificationsWithDeviceToken, ensuring Firebase
|
||||||
|
// receives a fresh APNs token regardless of whether permission was already granted.
|
||||||
|
application.registerForRemoteNotifications()
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlutterImplicitEngineDelegate can interfere with Firebase's method swizzling,
|
||||||
|
// preventing it from capturing the APNs token. Forward it explicitly instead.
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
||||||
|
) {
|
||||||
|
Messaging.messaging().apnsToken = deviceToken
|
||||||
|
super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 571 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.6 KiB |
@@ -3,13 +3,13 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>API_KEY</key>
|
<key>API_KEY</key>
|
||||||
<string>AIzaSyC0MWniqI8flETaT8zKwXQzBhYRljKIKvk</string>
|
<string>AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo</string>
|
||||||
<key>GCM_SENDER_ID</key>
|
<key>GCM_SENDER_ID</key>
|
||||||
<string>956683546941</string>
|
<string>956683546941</string>
|
||||||
<key>PLIST_VERSION</key>
|
<key>PLIST_VERSION</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>BUNDLE_ID</key>
|
<key>BUNDLE_ID</key>
|
||||||
<string>com.example.blindMaster</string>
|
<string>com.adipu.blindMaster</string>
|
||||||
<key>PROJECT_ID</key>
|
<key>PROJECT_ID</key>
|
||||||
<string>blindmaster-54055</string>
|
<string>blindmaster-54055</string>
|
||||||
<key>STORAGE_BUCKET</key>
|
<key>STORAGE_BUCKET</key>
|
||||||
@@ -25,6 +25,6 @@
|
|||||||
<key>IS_SIGNIN_ENABLED</key>
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
<true></true>
|
<true></true>
|
||||||
<key>GOOGLE_APP_ID</key>
|
<key>GOOGLE_APP_ID</key>
|
||||||
<string>1:956683546941:ios:162a6b8aa58f1eb8121554</string>
|
<string>1:956683546941:ios:1059be0ae683894b121554</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||||
<string>This app uses Bluetooth to connect to nearby devices.</string>
|
<string>This app uses Bluetooth to provision BlindMaster devices for the first time.</string>
|
||||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||||
<string>This app requires Bluetooth access.</string>
|
<string>This app requires Bluetooth access.</string>
|
||||||
<key>NSBonjourServices</key>
|
<key>NSBonjourServices</key>
|
||||||
@@ -76,15 +76,13 @@
|
|||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict/>
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>production</string>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,18 +1,50 @@
|
|||||||
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
class FcmService {
|
class FcmService {
|
||||||
/// Request permission, fetch the FCM token, and register it with the server.
|
/// 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.
|
/// Safe to call on every login/session-restore — the server just upserts the value.
|
||||||
static Future<void> register() async {
|
static Future<void> register() async {
|
||||||
|
debugPrint('FCM: register() called');
|
||||||
try {
|
try {
|
||||||
final messaging = FirebaseMessaging.instance;
|
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();
|
final token = await messaging.getToken();
|
||||||
|
debugPrint('FCM TOKEN: ${token ?? "null — likely running on simulator"}');
|
||||||
if (token == null) return;
|
if (token == null) return;
|
||||||
await securePost({'token': token}, 'register_fcm_token');
|
await securePost({'token': token}, 'register_fcm_token');
|
||||||
} catch (_) {
|
} catch (e) {
|
||||||
// Non-fatal — push notifications simply won't work until the next successful registration.
|
debugPrint('FCM registration failed: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,21 +59,21 @@ class DefaultFirebaseOptions {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions ios = FirebaseOptions(
|
static const FirebaseOptions ios = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyC0MWniqI8flETaT8zKwXQzBhYRljKIKvk',
|
apiKey: 'AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo',
|
||||||
appId: '1:956683546941:ios:162a6b8aa58f1eb8121554',
|
appId: '1:956683546941:ios:1059be0ae683894b121554',
|
||||||
messagingSenderId: '956683546941',
|
messagingSenderId: '956683546941',
|
||||||
projectId: 'blindmaster-54055',
|
projectId: 'blindmaster-54055',
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
||||||
iosBundleId: 'com.example.blindMaster',
|
iosBundleId: 'com.adipu.blindMaster',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions macos = FirebaseOptions(
|
static const FirebaseOptions macos = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyC0MWniqI8flETaT8zKwXQzBhYRljKIKvk',
|
apiKey: 'AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo',
|
||||||
appId: '1:956683546941:ios:162a6b8aa58f1eb8121554',
|
appId: '1:956683546941:ios:1059be0ae683894b121554',
|
||||||
messagingSenderId: '956683546941',
|
messagingSenderId: '956683546941',
|
||||||
projectId: 'blindmaster-54055',
|
projectId: 'blindmaster-54055',
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
||||||
iosBundleId: 'com.example.blindMaster',
|
iosBundleId: 'com.adipu.blindMaster',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions windows = FirebaseOptions(
|
static const FirebaseOptions windows = FirebaseOptions(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
|
||||||
import 'package:blind_master/BlindMasterScreens/Startup/splash_screen.dart';
|
import 'package:blind_master/BlindMasterScreens/Startup/splash_screen.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
@@ -16,6 +17,7 @@ void main() async {
|
|||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
||||||
|
FirebaseMessaging.instance.onTokenRefresh.listen((_) => FcmService.register());
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||