Не удается получить push-уведомление, нажмите «Работать все время».

# #android #firebase #flutter #push-notification #firebase-cloud-messaging

Вопрос:

Я пытаюсь внедрить push-уведомления в наше приложение, и я добился некоторого успеха после нескольких бессонных часов, вызванных несоответствиями версий и плохой документацией.

Мне удалось получать и показывать уведомления, когда приложение завершается, когда оно работает в фоновом режиме и когда оно работает на переднем плане.

Но у меня есть две проблемы, которые я пытаюсь решить в течение нескольких часов:

  1. Иногда уведомление отображается дважды
  2. Только второе уведомление, которое появилось (из первого выпуска), выполняет действие, которое я ему назначаю. Иногда он выполняет это примерно 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 глобальной константы, это было внутри класса или что-то в этом роде, кажется, это важно, и это действительно трудно найти в документации.