мы включаем push-уведомление с помощью Firebase в нашем приложении Flutter, но оно возвращает эту ошибку на моем реальном устройстве, когда я хочу войти в систему. Я не знаю, где ошибка, и это происходит только с IOS. У Андроида проблем нет. Я тоже следил за официальной документацией. Xcode: 15.2, Флаттер: 3.19.5
вот сообщение об ошибке:
FLTFirebaseMessaging: An error occurred while calling method Messaging#getToken, errorOrNil => {
NSErrorFailingURLKey = "https://device-provisioning.googleapis.com/checkin";
NSErrorFailingURLStringKey = "https://device-provisioning.googleapis.com/checkin";
NSLocalizedDescription = "The request timed out.";
"_NSURLErrorFailingURLSessionTaskErrorKey" = "LocalDataTask <9BEF5303-AEAA-4005-9A7D-D8307A35D3D5>.<1>";
"_NSURLErrorRelatedURLSessionTaskErrorKey" = (
"LocalDataTask <9BEF5303-AEAA-4005-9A7D-D8307A35D3D5>.<1>"
);
"_kCFStreamErrorCodeKey" = "-2103";
"_kCFStreamErrorDomainKey" = 4;
}
вот как я инициализирую код initFirebase для токена:
Future<void> initFirebase() async {
String? fcmToken;
await Firebase.initializeApp(
options: FirebaseOptions(
apiKey: Platform.isAndroid
? "AIzaSyBuRrD9IUg721orGNJzUPw_6jBqzW0qbgcw"
: "AIzaSyDpy26KbxDkillvYaBlX_lqvmXC1XOQSpA",
appId: Platform.isAndroid
? "1:199061089561:android:bc4deb3u87dd11a1af0d90"
: '1:199061089961:ios:09e1ew1avp141a86af0d90',
messagingSenderId: "199061680561",
iosBundleId: "com.flutter.truck",
storageBucket: "truck-19121.appspot.com",
projectId: "truck-19121"));
if (Platform.isAndroid) {
fcmToken = await FirebaseMessaging.instance.getToken();
} else if (Platform.isIOS) {
fcmToken = await FirebaseMessaging.instance.getAPNSToken();
if (fcmToken != null) {
await Future<void>.delayed(
const Duration(
seconds: 5,
),
);
fcmToken = await FirebaseMessaging.instance.getAPNSToken();
}
}
printColored("FCM USER TOKEN: $fcmToken", PrintedColors.red);
// FOREGROUND MESSAGE HANDLING.
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
debugPrint(
"NOTIFICATION FOREGROUND MODE: ${message.notification!.title} in foreground");
debugPrint("NOTIFICATION DATA: ${message.data} in terminated");
LocalNotificationService.localNotificationService
.showRemoteNotification(message);
});
// BACkGROUND MESSAGE HANDLING
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
// FROM TERMINATED MODE
handleMessage(RemoteMessage message) {
debugPrint(
"NOTIFICATION FROM TERMINATED MODE: ${message.notification!.title} in terminated");
debugPrint("NOTIFICATION DATA: ${message.data} in terminated");
LocalNotificationService.localNotificationService
.showRemoteNotification(message);
}
RemoteMessage? remoteMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (remoteMessage != null) {
handleMessage(remoteMessage);
}
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
}
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
LocalNotificationService.localNotificationService
.showRemoteNotification(message);
debugPrint(
"NOTIFICATION BACKGROUND MODE: ${message.notification!.title} in background");
debugPrint("NOTIFICATION DATA: ${message.data} in terminated");
}
Вам необходимо запросить разрешение для iOS, прежде чем запрашивать apnsToken.
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);
А для ios вам также необходимо запросить токен через getToken(), Токен FCM, полученный через getToken(), отличается от apnsToken, полученного с помощью apnsToken(). Сначала вам необходимо получить apnsToken для ios, если оно не равно нулю, вам нужно запросить токен fcm с помощью метода getToken().
В основном ApnsToken — это токен, специфичный для Apple, а токен fcm, полученный getToken (), используется для отправки или получения уведомлений с сервера fcm.
Ниже приведен полный код, необходимый для FCM (локальное уведомление для переднего плана Android не включено в это)
main.dart
void main() async {
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await PushNotificationService().initNotifications();
}
fcm_service.dart
final FirebaseMessaging messaging = FirebaseMessaging.instance;
@pragma('vm:entry-point')
Future<void> handleBackgroundMessage(RemoteMessage message) async {
handleMessage(message);
}
handleMessage(RemoteMessage? message) {
if (message == null) return;
// can do anything here with message. Like navigating to some s reen depending upon the message
}
class PushNotificationService {
Future<void> initNotifications() async {
try {
await messaging.requestPermission(provisional: true);
if (Platform.isIOS) {
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
if (apnsToken == null) {
// APNS token is available, make FCM plugin API requests...
log('apnsToken is null');
return;
}
}
final fcmToken = await messaging.getToken();
log('device Token: $fcmToken');
if (fcmToken != null) {
await initPushNotifications();
FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) {
//do something on token refresh
}).onError((err) {
log(err.toString());
});
}
} catch (e) {
log(e.toString());
}
}
Future initPushNotifications() async {
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
FirebaseMessaging.instance.getInitialMessage().then(handleMessage);
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage);
FirebaseMessaging.onMessage.listen(createLocalNotification);
У меня была аналогичная проблема: токен APNS вернулся, но не токен устройства. Я поднял аналогичный вопрос. Сегодня я решил проблему — она была связана с тем, что для ключа iOS не были настроены разрешения в API и службах в Google Cloud Console. Полная информация здесь: https://stackoverflow.com/a/78272520/4173169