dev/flutter

flutter - 백그라운드 푸시 메세지 클릭 이벤트

wlrn566 2023. 7. 10. 13:51

백그라운드에서 푸시 알람이 왔을 때 해당 알람을 클릭하면 앱이 켜지게 된다.

하지만 알람의 종류나 내용에 따라 메인화면이 아닌 지정된 화면이 나와야 할 때가 있다.

 

공식 예제를 보면 onMessageOpenedApp()를 사용하면 된다고 한다.

 

1. 푸시 알람 이벤트 코드 추가

플러터에서 화면 전환등을 할 때 context가 필요하다.

그런데 푸시 알람을 클릭했을 때는 차근차근 위젯트리를 밟고 가는 것이 아니라 바로 어떤 페이지로 전환을 시킨다.

그러기 위해 context없이 navigatorKey를 이용하여야 한다.

 

// 백그라운드 수신
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    log("백그라운드에서 푸시 클릭");
    if(message.data['id'] == '1') {
      SchedulerBinding.instance.addPostFrameCallback((_) {
        Navigator.of(GlobalVariable.navigatorKey.currentContext!) // navigatorKey사용
          .push(MaterialPageRoute(
          builder: (context) => FirstPage()));
      });
      return;
    }
  });

 

2. navigatorKey 선언

 

// GlobalKey 만들기
class GlobalVariable {
  static final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
}

// main.dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: GlobalVariable.navigatorKey, // context 없이 라우팅을 위함
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyWidget()
    );
  }
}

 

 


import 'dart:developer';

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_notification/first.dart';
import 'package:flutter_notification/global.dart';
import 'package:flutter_notification/second.dart';

@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  // await Firebase.initializeApp();

  // print("Handling a background message: ${message.messageId}");
  log("background message data: ${message.data}");
}

Future<void> setNotification() async {

  // 채널 생성
  var channel = const AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // name
    description: 'This channel is used for important notifications.', // description
    importance: Importance.high,
  );

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

  // 포그라운드 메세지 수신
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    // print('Got a message whilst in the foreground!');
    log('forground message data: ${message.data}');

    if (message.notification != null) {
      print('Message also contained a notification: ${message.notification}');
      
      // 포그라운드에서 푸시 알람 클릭 시
      // if (message.data['id'] == '1') {
      //   Navigator.of(GlobalVariable.navigatorKey.currentContext!)
      //     .push(MaterialPageRoute(
      //     builder: (context) => SecondPage()));
      // }

      flutterLocalNotificationsPlugin.show(
        message.hashCode,
        message.notification?.title,
        message.notification?.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            channel.id,
            channel.name,
            channelDescription: channel.description,
            icon: '@mipmap/ic_launcher',
          ),
          iOS: const DarwinNotificationDetails(
            badgeNumber: 1,
            subtitle: 'subtitle',
            sound: 'slow_spring_board.aiff',
          )
        )
      );
    }
  });

  // 백그라운드 수신
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    log("백그라운드에서 수신");
    if(message.data['id'] == '1') {
      SchedulerBinding.instance.addPostFrameCallback((_) {
        Navigator.of(GlobalVariable.navigatorKey.currentContext!)
          .push(MaterialPageRoute(
          builder: (context) => FirstPage()));
      });
      return;
    }
  });
}