首页 > 解决方案 > 当应用程序处于后台或在 iOS 或 Android 抖动中终止时,通知不会出现

问题描述

当应用程序处于后台或在 iOS 或 Android 中终止时通知未出现 .. 在 android 中,当应用程序处于后台并且通知出现时我看到此错误,但在 iOS 中,通知出现在后台,但在应用程序终止时没有。“由于没有注册 onBackgroundMessage 处理程序,因此无法在 Dart 中处理后台消息。” -- 控制台中的 Android 错误

这是我在 main.dart 中的通知代码:

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Common/Repository.dart';
import 'Controllers/Login.dart';
import 'Controllers/SplashScreen.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseMessaging.onBackgroundMessage(
      (message) => _firebaseMessagingBackgroundHandler(message));
  runApp(CyberEngine());
}

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  final AndroidNotificationChannel channel = AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // title
    'This channel is used for important notifications.', // description
    importance: Importance.max,
  );
  final data = message.data;
  print(data.toString());
  RemoteNotification? notification = message.notification;
  AndroidNotification? android = message.notification?.android;
  // var initializationSettingsAndroid =
  //     new AndroidInitializationSettings('ic_launcher');
  flutterLocalNotificationsPlugin.show(
      notification.hashCode,
      "${data['title'].toString()}",
      "${data['body'].toString()}",
      NotificationDetails(
        android: AndroidNotificationDetails(
          channel.id,
          channel.name,
          channel.description,
          // TODO add a proper drawable resource to android, for now using
          //      one that already exists in example app.
          icon: 'ic_launcher',
        ),
        iOS: IOSNotificationDetails(
          presentBadge: true,
          presentAlert: true,
          presentSound: true,
        ),
      ));
}

class CyberEngine extends StatelessWidget {
  Future setupNotifications() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;

    NotificationSettings settings = await messaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      print('User granted permission');
    } else if (settings.authorizationStatus ==
        AuthorizationStatus.provisional) {
      print('User granted provisional permission');
    } else {
      print('User declined or has not accepted permission');
    }

    await FirebaseMessaging.instance
        .setForegroundNotificationPresentationOptions(
      alert: true, // Required to display a heads up notification
      badge: true,
      sound: true,
    );

    await messaging.requestPermission();

    const AndroidNotificationChannel channel = AndroidNotificationChannel(
      'high_importance_channel', // id
      'High Importance Notifications', // title
      'This channel is used for important notifications.', // description
      importance: Importance.max,
    );

    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();

    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('ic_launcher');

    final IOSInitializationSettings initializationSettingsIOS =
        IOSInitializationSettings(
      requestAlertPermission: false,
      requestBadgePermission: false,
      requestSoundPermission: false,
    );

    const MacOSInitializationSettings initializationSettingsMacOS =
        MacOSInitializationSettings(
      requestAlertPermission: false,
      requestBadgePermission: false,
      requestSoundPermission: false,
    );

    final InitializationSettings initializationSettings =
        InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsIOS,
      macOS: initializationSettingsMacOS,
    );

    await flutterLocalNotificationsPlugin.initialize(initializationSettings);

    await flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<
            AndroidFlutterLocalNotificationsPlugin>()
        ?.createNotificationChannel(channel);

    final token = await messaging.getToken();
    print('FCM TOKEN: $token');
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString("FCMID", token ?? "");

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      final data = message.data;
      print(data.toString());
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;
      flutterLocalNotificationsPlugin.show(
          notification.hashCode,
          "${data['title'].toString()}",
          "${data['body'].toString()}",
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel.id,
              channel.name,
              channel.description,
              // TODO add a proper drawable resource to android, for now using
              //      one that already exists in example app.
              icon: 'ic_launcher',
            ),
            iOS: IOSNotificationDetails(
              presentBadge: true,
              presentAlert: true,
              presentSound: true,
            ),
          ));
    });

    // FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    //   print('A new onMessageOpenedApp event was published!');
    //   // Navigator.pushNamed(context, '/message',
    //   //     arguments: MessageArguments(message, true));
    //   print(message.data.toString());
    // });

    return;
  }

  Future<void> setupInteractedMessage() async {
    // Get any messages which caused the application to open from
    // a terminated state.
    RemoteMessage? initialMessage =
        await FirebaseMessaging.instance.getInitialMessage();

    // FirebaseMessaging.instance
    //     .getInitialMessage()
    //     .then((RemoteMessage message) {
    //   if (message != null) {
    //     Navigator.pushNamed(context, '/message',
    //         arguments: MessageArguments(message, true));
    //   }
    // });
  }

  // void _handleMessage(RemoteMessage message) {
  //   if (message.data['type'] == 'chat') {
  //     Navigator.pushNamed(
  //       context,
  //       '/chat',
  //       arguments: ChatArguments(message),
  //     );
  //   }
  // }

  @override
  Widget build(BuildContext context) {
    setupNotifications();
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: FutureBuilder(
        future: setupNotifications(),
        builder: (context, snapshot) {
          // Check for errors
          if (snapshot.hasError) {
            // return SomethingWentWrong();
          }

          // Once complete, show your application
          if (snapshot.connectionState == ConnectionState.done) {
            return SplashScreen();
          }

          // Otherwise, show something whilst waiting for initialization to complete
          return WillPopScope(
              child: Scaffold(
                  backgroundColor: AppColors.AppPrimaryColor,
                  body: Stack(children: [
                    Image.asset(
                      'lib/assets/splash.png',
                      fit: BoxFit.contain,
                      height: double.infinity,
                      width: double.infinity,
                      alignment: Alignment.center,
                    ),
                    Align(
                        alignment: Alignment.bottomCenter,
                        child: Container(
                          padding: EdgeInsets.only(bottom: 50),
                          child: CircularProgressIndicator(color: Colors.white),
                        ))
                  ])),
              onWillPop: () {
                return Future.value(false); // if true allow back else block it
              });
        },
      ),
    );
  }
}

我还按照我的android项目中的建议创建了一个文件名Application.kt,其代码是:package com.example.cyber_engine

import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingBackgroundExecutor
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingBackgroundService
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin
import io.flutter.plugins.pathprovider.PathProviderPlugin


class MyApplication : FlutterApplication(), PluginRegistrantCallback {

    override
    fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingBackgroundService.setPluginRegistrant(this)
        FlutterFirebaseMessagingBackgroundExecutor.setPluginRegistrant(this)
    }

    override
    fun registerWith(registry: PluginRegistry) {
        PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"))
        FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"))
        FlutterFirebaseMessagingPlugin.registerWith(registry.registrarFor("plugins.flutter.io/firebase_messaging"))
    }
}

将以下行添加到 manifest.xml

<meta-data
              android:name="com.google.firebase.messaging.default_notification_channel_id"
              android:value="high_importance_channel" />

我不知道还能做什么。请帮助某人..

标签: flutterdart

解决方案


推荐阅读