Skip to content

Commit a6b9f3e

Browse files
russellwheatleykevinthecheung
authored andcommitted
fix(messaging): Throw exception if APNS token is not yet available (#11400)
Co-authored-by: Kevin Cheung <[email protected]>
1 parent bc65b15 commit a6b9f3e

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

docs/cloud-messaging/client.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,20 @@ To retrieve the current registration token for an app instance, call
144144
ask the user for notification permissions. Otherwise, it returns a token or
145145
rejects the future due to an error.
146146
147+
Warning: In iOS SDK 10.4.0 and higher, it is a requirement that the APNs token
148+
is available before making API requests. The APNs token is not guaranteed to have been received
149+
before making FCM plugin API requests.
150+
147151
```dart
148-
final fcmToken = await FirebaseMessaging.instance.getToken();
152+
// You may set the permission requests to "provisional" which allows the user to choose what type
153+
// of notifications they would like to receive once the user receives a notification.
154+
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);
155+
156+
// For apple platforms, ensure the APNS token is available before making any FCM plugin API calls
157+
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
158+
if (apnsToken != null) {
159+
// APNS token is available, make FCM plugin API requests...
160+
}
149161
```
150162
151163
On web platforms, pass your VAPID public key to `getToken()`:

packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/method_channel/method_channel_messaging.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// BSD-style license that can be found in the LICENSE file.
55

66
import 'dart:async';
7+
import 'dart:io' show Platform;
78
import 'dart:ui';
89

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

130+
// Created this to check APNS token is available before certain Apple Firebase
131+
// Messaging requests. See this issue:
132+
// https://github.com/firebase/flutterfire/issues/10625
133+
Future<void> _APNSTokenCheck() async {
134+
if (Platform.isMacOS || Platform.isIOS) {
135+
String? token = await getAPNSToken();
136+
137+
if (token == null) {
138+
throw FirebaseException(
139+
plugin: 'firebase_messaging',
140+
code: 'apns-token-not-set',
141+
message:
142+
'APNS token has not been set yet. Please ensure the APNS token is available by calling `getAPNSToken()`.',
143+
);
144+
}
145+
}
146+
}
147+
129148
@override
130149
FirebaseMessagingPlatform delegateFor({required FirebaseApp app}) {
131150
return MethodChannelFirebaseMessaging(app: app);
@@ -189,6 +208,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {
189208

190209
@override
191210
Future<void> deleteToken() async {
211+
await _APNSTokenCheck();
212+
192213
try {
193214
await channel
194215
.invokeMapMethod('Messaging#deleteToken', {'appName': app.name});
@@ -220,6 +241,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {
220241
Future<String?> getToken({
221242
String? vapidKey, // not used yet; web only property
222243
}) async {
244+
await _APNSTokenCheck();
245+
223246
try {
224247
Map<String, String?>? data =
225248
await channel.invokeMapMethod<String, String>('Messaging#getToken', {
@@ -364,6 +387,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {
364387

365388
@override
366389
Future<void> subscribeToTopic(String topic) async {
390+
await _APNSTokenCheck();
391+
367392
try {
368393
await channel.invokeMapMethod('Messaging#subscribeToTopic', {
369394
'appName': app.name,
@@ -376,6 +401,8 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform {
376401

377402
@override
378403
Future<void> unsubscribeFromTopic(String topic) async {
404+
await _APNSTokenCheck();
405+
379406
try {
380407
await channel.invokeMapMethod('Messaging#unsubscribeFromTopic', {
381408
'appName': app.name,

0 commit comments

Comments
 (0)