# #android #firebase #flutter #push-notification #firebase-cloud-messaging
Вопрос:
Я пытаюсь внедрить push-уведомления в наше приложение, и я добился некоторого успеха после нескольких бессонных часов, вызванных несоответствиями версий и плохой документацией.
Мне удалось получать и показывать уведомления, когда приложение завершается, когда оно работает в фоновом режиме и когда оно работает на переднем плане.
Но у меня есть две проблемы, которые я пытаюсь решить в течение нескольких часов:
- Иногда уведомление отображается дважды
- Только второе уведомление, которое появилось (из первого выпуска), выполняет действие, которое я ему назначаю. Иногда он выполняет это примерно 2-3 раза.
onNotificationClick, который я назначаю getInitialMessage и onMessageOpenedApp, редко выполняется вообще, когда я нажимаю на уведомление. Такое ощущение, что флаттер не знает, что ему назначен слушатель.
Это код, с которым я работаю до сих пор (разделен только на необходимые части)
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'***censored***_notification_channel', // id
'***censored*** Notifications', // title
'', // description
importance: Importance.high,
);
/// This is called on the beginning of main() to ensure when app is closed
/// user receives the notifications. Then it's called also in the build method of MyApp
/// so user receives foreground notifications.
Future<void> showNotification(RemoteMessage message) async {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null amp;amp; android != null) {
printWarning("Showing notification");
localNotifications.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
icon: android?.smallIcon,
),
),
);
}
}
/// This is called when user clicks on the notification
Future<void> onNotificationClick(RemoteMessage message) async {
printWarning("Clicked on notification");
if (message == null || message?.data == null) {
printError("onMessageClick: Message or message.data is null");
return;
}
final Map data = message?.data;
printWarning("onMessageClick: Message is not null");
if (data['screen'] != null amp;amp; data['screen_args'] != null) {
switch (message.data['screen']) {
case 'PostScreen':
PostsProvider _postsProvider = Provider.of(
navigatorKey.currentContext,
listen: false,
);
_postsProvider.fetchPosts(reload: true).then((List<Post> posts) {
Post post = posts.firstWhere((element) {
Map<String, dynamic> _screenArgs =
jsonDecode(message.data['screen_args']);
return element.id == _screenArgs['post'];
});
Navigator.of(navigatorKey.currentContext).pushNamed(
'/post', arguments: {
'post': post,
});
});
break;
}
}
}
final FlutterLocalNotificationsPlugin localNotifications =
FlutterLocalNotificationsPlugin();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await localNotifications
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
// Permissions for background notifications
await FirebaseMessaging.instance.requestPermission(
alert: true,
badge: true,
sound: true,
);
// Permissions for foreground notifications
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
// Local notification settings, which allows to make foreground notifications
await localNotifications.initialize(InitializationSettings(
android: AndroidInitializationSettings("@drawable/icon"),
iOS: IOSInitializationSettings(),
));
FirebaseMessaging.onMessageOpenedApp.listen(onNotificationClick);
FirebaseMessaging.instance.getInitialMessage().then(onNotificationClick);
FirebaseMessaging.onBackgroundMessage(showNotification);
runApp(MultiProvider(
providers: [
...
],
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
FirebaseMessaging.onMessage.listen(showNotification);
FirebaseMessaging.onMessageOpenedApp.listen(onNotificationClick);
FirebaseMessaging.instance.getInitialMessage().then(onNotificationClick);
return Consumer<AuthProvider>(
builder: (BuildContext _context, authProvider, Widget child) {
return ...;
},
);
}
}
{уведомления: {планшет: {звука: по умолчанию, channelId: цензура_notification_channel, clickAction: FLUTTER_NOTIFICATION_CLICK}, название: мое push-уведомление, органа: новая статья только вышла, нажмите здесь, чтобы прочитать это :)}, данные: {screen_args: {«сообщение»:3231}, экран: PostScreen}, collapseKey: цензура, код: 0:1621934778096245-9232a32d9232a3, sentTime: 1621934777733, с: /темы/все, ТТЛ: 2419200}
[√] Flutter (Channel stable, 2.0.5, on Microsoft Windows [Version 10.0.19042.985], locale en-US)
• Flutter version 2.0.5 at C:Program Filesflutter
• Framework revision adc687823a (6 weeks ago), 2021-04-16 09:40:20 -0700
• Engine revision b09f014e96
• Dart version 2.12.3
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
• Android SDK at C:UserserikkAppDataLocalAndroidsdk
• Platform android-30, build-tools 30.0.3
• Java binary at: C:Program FilesAndroidAndroid Studiojrebinjava
• Java version OpenJDK Runtime Environment (build 11.0.8 10-b944.6842174)
• All Android licenses accepted.
[√] Chrome - develop for the web
• Chrome at C:Program FilesGoogleChromeApplicationchrome.exe
[√] Android Studio (version 4.1.0)
• Android Studio at C:Program FilesAndroidAndroid Studio
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.8 10-b944.6842174)
[√] VS Code, 64-bit edition (version 1.55.2)
• VS Code at C:Program FilesMicrosoft VS Code
• Flutter extension can be installed from:
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[√] Connected device (3 available)
• VOG L29 (mobile) • EHT7N19308008035 • android-arm64 • Android 10 (API 29)
• Chrome (web) • chrome • web-javascript • Google Chrome 90.0.4430.212
• Edge (web) • edge • web-javascript • Microsoft Edge 90.0.818.66
• No issues found!
dependencies:
flutter:
sdk: flutter
intl: any
webview_flutter: any
cupertino_icons: ^1.0.2
flutter_secure_storage: ^4.1.0
http: ^0.13.0
provider: ^5.0.0
transparent_image: ^2.0.0
flutter_html: ^1.0.0
jwt_decoder: ^2.0.0
json_annotation:
advance_pdf_viewer: any
path_provider: ^1.6.11
url_launcher: ^6.0.2
flutter_inappwebview: ^5.2.1
fluttertoast: ^8.0.4
jwt_decode: ^0.3.1
photo_view: ^0.11.1
flutter_svg: ^0.20.0-nullsafety.3
firebase_messaging: any
firebase_core: ^0.7.0
flutter_local_notifications: ^4.0.1 2
flutter_keyboard_visibility: ^4.0.6
flutter_cached_pdfview: any
flutter_cache_manager: any
Спасибо вам за любые рекомендации
Комментарии:
1. Проблема дублирования известна, вы можете прочитать об этом подробнее здесь: github.com/FirebaseExtended/flutterfire/issues/1669
2. @MidhunMP спасибо, но меня больше беспокоит тот факт, что я нажимаю на уведомление, а мое приложение onMessageOpenedApp и getInitialMessage.listen не выполняются. Кроме того, я понятия не имею, верен ли мой код. И, к сожалению, когда я попытался использовать любую другую версию FCM, все мое приложение сломалось или вообще не работало.
3. Я не знаю, будет ли это полезно, но я обнаружил конфликт между FirebaseMessaging и advance_pdf_viewer (который, как я вижу, вы также используете). В моем случае, когда у меня настроен файл FirebaseMessaging.onBackgroundMessage, я не могу отобразить свой PDF-файл. Когда я комментирую FirebaseMessaging.onBackgroundMessage, мой просмотрщик PDF работает нормально. Я предполагаю, что эти проблемы связаны.
4. Моя проблема, если я помню, была вызвана отсутствием у обработчика onBackgroundMessage глобальной константы, это было внутри класса или что-то в этом роде, кажется, это важно, и это действительно трудно найти в документации.