#firebase #flutter #google-cloud-functions #firebase-cloud-messaging
#firebase #flutter #google-cloud-функции #firebase-облако-обмен сообщениями
Вопрос:
У меня было некоторое время с момента push-уведомления, когда я работал над своим приложением, у меня есть коллекция Firestore, которая при создании новых документов запускает функцию sendNotification.
Раньше функция выглядела так:
export const sendChatNotification = functions.firestore.document('chatrooms/{chatroomId}/chats/{chatId}').onCreate(async (snap, ctx) => {
//In Comment OLD Way to get info data for the notification
const token = snap.get('sendToDeviceToken'); //snap.data().sendToDeviceToken;
const sender = snap.get('fullSenderName'); //snap.data().fullSenderName;
const body = snap.get('message'); //snap.data().message;
const payload = {
notification: {
title: sender,
body: body,
}
};
return admin.messaging().sendToDevice(token, payload).then(response => {
console.log('Message Function Executed sent to device with token: ' token ' from sender: ' sender ' with message: ' body );
});
}
Это немного поработало, но перестало работать, хотя во всех журналах указано, что оно завершается со статусом ok.
Теперь мой коллега сказал мне, что ему пришлось изменить этот код для новой функции, которая выглядит следующим образом:
export const sendChatNotification = functions.firestore.document('chatrooms/{chatroomId}/chats/{chatId}').onCreate(async (snap, ctx) => {
//In Comment OLD Way to get info data for the notification
const token = snap.get('sendToDeviceToken'); //snap.data().sendToDeviceToken;
const sender = snap.get('fullSenderName'); //snap.data().fullSenderName;
const body = snap.get('message'); //snap.data().message;
var tokens = [];
tokens.push(token)
const payload = {
notification: {
title: sender,
body: body,
},
android: {
notification: {
channelId: "roofdeck_default",
click_action: 'FLUTTER_NOTIFICATION_CLICK',
title: sender,
body: body,
}
},
apns: {
headers: {
"apns-push-type": "alert"
},
payload: {
aps: {
category: "FLUTTER_NOTIFICATION_CLICK"
}
},
},
data: {
postID: snap.id,
type: "POST_TAG",
},
tokens: token
}
if (token.length > 0) {
await fcm.sendMulticast(payload);
}
});
Для полноты мы добавили эту строку кода после инициализации приложения:
const fcm = admin.messaging();
Он также упомянул, что для этого ему пришлось создать канал для Android, поэтому я последовал руководству и изменил свой Main в приложении Flutter:
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'roofdeck_default',
'RoofDeck Notification Channel',
description: 'This Channel is for RoofDeck Chat Notifications',
importance: Importance.high,
playSound: true,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('A Background Message just showed up: ${message.messageId}');
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
runApp(MyApp());
}
И на начальном экране я добавляю этот код в Init, чтобы он работал:
@override
void initState() {
//_isIos = Platform.isIOS;
fbm.requestPermission();
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('En OnMessage: ${message.notification.body.toString()}');
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null amp;amp; android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
color: Colors.blue,
playSound: true,
icon: '@mipmap/ic_launcher',
),
),
);
}
//return;
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
print('En onMessageOpenedApp: ${message.notification.body.toString()}');
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null amp;amp; android != null) {
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text(notification.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(notification.body),
],
),
),
);
});
}
//return;
});
_saveToken();
super.initState();
}
Наконец, чтобы сгенерировать последний токен, я сохраняю токен в Firestore:
Future<void> _saveToken() async {
try {
token = await fbm.getToken();
var user = FirebaseAuth.instance.currentUser;
if (token != null amp;amp; user != null) {
FirebaseFirestore.instance.collection('users').doc(user.uid).update({
'token': token,
'tokenCreatedAt': DateTime.now(),
'platform': Platform.operatingSystem,
});
}
} catch (e) {
print("Messaging(_saveToken): $e");
}
}
Я попробовал на устройстве iPhone, и через 2 часа уведомление по-прежнему не получено, хотя я вижу, что журналы новой облачной функции работают правильно.
Любые идеи, что не так, почему, по крайней мере, на iPhone не работают уведомления.
С уважением,
Комментарии:
1. Используете ли вы эмулятор iOS, если он не будет работать, кроме того, для iOS вам необходимо настроить службы APN от Apple с помощью firebase и использовать токен apn для отправки уведомления
2. Где я могу получить APN? Извините
3. Для iOS вы можете обратиться к этой странице firebase.flutter.dev/ docs/ messaging / apple-интеграция , она довольно длинная, поэтому я не могу дать вам подробную информацию в комментарии.