flutter - 当我在 Flutter 的前台或后台单击 Firebase 推送通知时导航到另一个屏幕

标签 flutter firebase dart firebase-cloud-messaging

我在我的 Flutter 应用程序中使用 Firebase 消息传递,即使我的应用程序处于前台或后台,我也想在点击通知时导航到另一个屏幕,我使用了很多功能,但它不会触发点击事件,我可以找不到任何东西可以解决我的问题。

当我在应用程序处于前台或后台时单击通知时,没有任何反应,因为它导航到同一页面。 当我在应用程序终止时单击通知时,它会在启动画面上打开并转到主页而不是我想要的屏幕。

我在我的 Manifest 中添加了这个 intent-filter

  <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

然后我将其添加到 Json 对象

"click_action": "FLUTTER_NOTIFICATION_CLICK",

下面是如何在 main.dart

中获取后台 FCM
const AndroidNotificationChannel channel = AndroidNotificationChannel(
    'high_importance', // id
    'High Importance Notifications', // title
    importance: Importance.high,
    playSound: true);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();


Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  SessionManager sessionManager = SessionManager();

  await Firebase.initializeApp();
  //final sound = 'sound.mp3';
  print('A bg message just showed up :  ${message.messageId}');

  final android = AndroidInitializationSettings('@mipmap/ic_launcher');
  final ios = IOSInitializationSettings(
    requestSoundPermission: false,
    requestBadgePermission: false,
    requestAlertPermission: false,);
  final settings = InitializationSettings(android: android,iOS: ios);
  flutterLocalNotificationsPlugin.initialize(settings,);
  if(message.data['title'].toString().toLowerCase()=="new request") {
    sessionManager.getBadge().then((badge) {
      if (badge != null) {
        int x = badge + 1;
        sessionManager.saveBadge(x);
        print("notification number is " + x.toString());
      }
      else {
        sessionManager.saveBadge(1);
      }
    });

  }

  flutterLocalNotificationsPlugin.show(
      message.data.hashCode,
      message.data['title'],
      message.data['body'],
      NotificationDetails(
        android: AndroidNotificationDetails(
          channel.id,
          channel.name,
          importance: Importance.high,
          priority: Priority.high,
         // sound: RawResourceAndroidNotificationSound(sound.split('.').first),
          playSound: true,
          icon: '@mipmap/ic_launcher',
        ),

      ));
  /*NotificationApi.showNotification(
      title: message.data['title'],
      body: message.data['body'],
      payload: "",
      id:  int.parse(channel.id));*/

}


Future<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(MyApps());
  // configLoading();

}


class MyApps extends StatefulWidget {
  const MyApps({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return MyApp();
  }
}


class MyApp extends State<MyApps> {
  static  ValueNotifier<int> strikeNotifier = ValueNotifier(0);

  Color _primaryColor =  Color(0xff0d8b75);


  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      builder: () => MaterialApp(
        debugShowCheckedModeBanner: false,
        home: SplashScreen(),
      ),
      designSize: const Size(1080, 2280),
    );
  }


  void showNotification(String title, String body) async {
    await _demoNotification(title, body);
  }

  Future<void> _demoNotification(String title, String body) async {
    var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        'channel_I', 'channel name',
        showProgress: true,
        priority: Priority.high,
        playSound: true,
        ticker: 'test ticker');

    var iOSChannelSpecifics = IOSNotificationDetails();
    var platformChannelSpecifics = NotificationDetails(
        android: androidPlatformChannelSpecifics, iOS: iOSChannelSpecifics);
    await flutterLocalNotificationsPlugin
        .show(0, title, body, platformChannelSpecifics, payload: 'test');
  }

  @override
  void initState() {
    super.initState();

       FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
  if (message != null) {
    Navigator.push(context, MaterialPageRoute(builder: (context)=>DoneAndPaiedPagess(0)));

  }
});

    getToken().then((value) {
      if(value!=null) {
        AppConstants.firebaseToken = value;
      }
    });


    FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    new FlutterLocalNotificationsPlugin();
    var initializationSettingsAndroid =  AndroidInitializationSettings('@mipmap/ic_launcher');
    var initializationSettingsIOS =  IOSInitializationSettings();
    var initializationSettings =  InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
    flutterLocalNotificationsPlugin.initialize(initializationSettings,
      );



    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      var data = message.data;
      //  AndroidNotification? android = message.notification?.android;/


      if (data != null ) {
        if(data['title'].toString().toLowerCase()=="new request") {
          SessionManager sessionManager = SessionManager(context);
          sessionManager.getBadge().then((badge) {
            if (badge != null) {
              setState(() {
                int x = badge + 1;
                strikeNotifier.value = x;
                sessionManager.saveBadge(x);
              });
            }
            else {
              strikeNotifier.value = 1;
              sessionManager.saveBadge(1);
            }
          });
        }
        print("entered");
        flutterLocalNotificationsPlugin.show(
            data.hashCode,
            data['title'],
            data['body'],
            NotificationDetails(
              android: AndroidNotificationDetails(
                channel.id,
                channel.name,
                playSound: true,
                icon: '@mipmap/ic_launcher',
              ),
            ));

      }
    });
   FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
  Navigator.push(context, MaterialPageRoute(builder: (context)=>DoneAndPaiedPagess(0)));

});
   
  }

  Future<String?> getToken() async{
    String? token = await FirebaseMessaging.instance.getToken();
    print("token is "+token!);
    return token;

  }
}

yaml

 firebase_core: ^1.12.0
  firebase_messaging: ^11.2.6
dependency_overrides:
  firebase_messaging_platform_interface: 3.1.6

编辑:从多个解决方案中,我尝试了最常见的解决方案,我在 initState 中使用了 onMessageOpenedApp 但它没有进入

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      Navigator.push(context, MaterialPageRoute(builder: (context)=>DoneAndPaiedPagess(0)));
    });

最佳答案

在您的代码中,您正在使用 flutter_local_notifications 插件,并且当您从 firebase 消息传递收到推送通知时,您正在创建本地通知。

由于通知不是由 firebase 消息传递创建的,因此您不会在 getInitialMessageonMessageOpenedApp 中获得点击回调。

为了获得本地通知的点击回调,您可以在初始化 flutter_local_notifications 时传递回调函数

flutterLocalNotificationsPlugin.initialize(initializationSettings,
    onSelectNotification: onSelectNotification);

void selectNotification(String payload) async {
    if (payload != null) {
      debugPrint('notification payload: $payload');
// Here you can check notification payload and redirect user to the respective screen
      await Navigator.push(
         context,
         MaterialPageRoute<void>(builder: (context) => SecondScreen(payload)),
      );
    }
}

更多的可以查看flutter_local_notifications文档

关于flutter - 当我在 Flutter 的前台或后台单击 Firebase 推送通知时导航到另一个屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72547014/

相关文章:

flutter - InteractiveViewer 在平移时不会隐藏其他小部件

firebase - Flutter Firestore 离线数据库

javascript - firebase 函数中无法访问全局变量

flutter : How can i get collection from document with cloud_firestore?

dart - 在style.css中引用sdk定义,例如color.dart

Flutter Listview 问题在顶部添加项目

google-maps-api-3 - 如何在我的 Flutter APP 中使用谷歌地图网络服务 API

android - Firebase 云消息传递是否需要服务器?

dart - 完成小部件动画后,在 Flutter 中运行一个函数

android - 如何在Flutter中使用文字识别?