Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/cloud-messaging/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,20 @@ To retrieve the current registration token for an app instance, call
ask the user for notification permissions. Otherwise, it returns a token or
rejects the future due to an error.

Warning: In iOS SDK 10.4.0 and higher, it is a requirement that the APNs token
is available before making API requests. The APNs token is not guaranteed to have been received
before making FCM plugin API requests.

```dart
final fcmToken = await FirebaseMessaging.instance.getToken();
// You may set the permission requests to "provisional" which allows the user to choose what type
// of notifications they would like to receive once the user receives a notification.
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);

// For apple platforms, ensure the APNS token is available before making any FCM plugin API calls
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
if (apnsToken != null) {
// APNS token is available, make FCM plugin API requests...
}
```

On web platforms, pass your VAPID public key to `getToken()`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:io' show Platform;
import 'dart:ui';

import 'package:firebase_core/firebase_core.dart';
Expand Down Expand Up @@ -126,6 +127,24 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {
static StreamController<String> tokenStreamController =
StreamController<String>.broadcast();

// Created this to check APNS token is available before certain Apple Firebase
// Messaging requests. See this issue:
// https://github.com/firebase/flutterfire/issues/10625
Future<void> _APNSTokenCheck() async {
if (Platform.isMacOS || Platform.isIOS) {
String? token = await getAPNSToken();

if (token == null) {
throw FirebaseException(
plugin: 'firebase_messaging',
code: 'apns-token-not-set',
message:
'APNS token has not been set yet. Please ensure the APNS token is available by calling `getAPNSToken()`.',
);
}
}
}

@override
FirebaseMessagingPlatform delegateFor({required FirebaseApp app}) {
return MethodChannelFirebaseMessaging(app: app);
Expand Down Expand Up @@ -189,6 +208,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {

@override
Future<void> deleteToken() async {
await _APNSTokenCheck();

try {
await channel
.invokeMapMethod('Messaging#deleteToken', {'appName': app.name});
Expand Down Expand Up @@ -220,6 +241,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {
Future<String?> getToken({
String? vapidKey, // not used yet; web only property
}) async {
await _APNSTokenCheck();

try {
Map<String, String?>? data =
await channel.invokeMapMethod<String, String>('Messaging#getToken', {
Expand Down Expand Up @@ -364,6 +387,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {

@override
Future<void> subscribeToTopic(String topic) async {
await _APNSTokenCheck();

try {
await channel.invokeMapMethod('Messaging#subscribeToTopic', {
'appName': app.name,
Expand All @@ -376,6 +401,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {

@override
Future<void> unsubscribeFromTopic(String topic) async {
await _APNSTokenCheck();

try {
await channel.invokeMapMethod('Messaging#unsubscribeFromTopic', {
'appName': app.name,
Expand Down