우선적으로 Flutter 앱 내에 Firebase를 추가하고, 등록하는 절차를 수행해야 한다.
아래 링크에서 시키는 대로 하자.

https://firebase.google.com/docs/flutter/setup?hl=ko&platform=ios

 

Flutter 앱에 Firebase 추가

Google은 흑인 공동체를 위한 인종적 평등을 추구하기 위해 노력하고 있습니다. 자세히 알아보기 이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English 의견 보내기 컬렉션을 사용해

firebase.google.com

1,2,3 단계 수행 이후

flutter pub add cloud_firestore
flutter pub add firebase_messaging
flutterfire configure
flutter run

 

위의 명령어를 이용해 Flutter app에 파이어스토어와 클라우드메세지 플러그인을 추가한다.
파이어스토어가 필요한 이유는 기기마다 앱의 고유한 주소가 형성되어 그쪽으로 알림을 보내게 되는데, 서버(Python)에서 그 주소(토큰)를 저장하고 조회하는 수단으로 DB를 사용하기 위함이다.

이 포스트에서는 안드로이드 대상으로만 구현한다. ios는 추가적인 설정이 필요함.

 

/android/build.gradle 

만약 빌드 시 sdk version 관련 에러가 뜨는 경우, compileSdkVersion 을 33으로 minSdkVersion을 32로 수정한다. 
임시 조치지만, 현재로써는 이게 최선.

 

/main.dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'firebase_options.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  print("Handling a background message: ${message.messageId}");
}

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  final fcmToken = await FirebaseMessaging.instance.getToken();
  await FirebaseFirestore.instance.collection("UserTokens").doc("User").set({
    'token': fcmToken,
  });
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      final snackBar = SnackBar(content: Text(message.data.toString()));
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(),
      floatingActionButton: FloatingActionButton(
        onPressed: (() => 0),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

맨 위에 선언된 Handler는 백그라운드를 담당하고, 포그라운드에서 메세지를 수신한 경우에는 MyHomePageState에서
실행된 FirebaseMessaging.onMessage.listen 리스너가 메세지를 수신하여 message로 콜백한다. 위의 예제는 스낵바를 이용해서 포그라운드 메세지를 출력할 뿐이다. 백그라운드 알림을 수정하기 위해서는 다른 설정을 해줘야 한다. 주의할 점은 main 에서 Firebase.InitializeApp()를 호출하는 부분에서 await 키워드를 사용했다는 점, 그리고 아래와 같이 fcmToken을 얻어서 파이어스토어에 송신한다는 점.

이제 콘솔에서 새 캠페인을 시작해서 테스트 메세지를 보내보면 백그라운드 상태와 포그라운드 상태일 때 Debug Console에서 수신했다는 메세지가 뜬다. 백그라운드 알림은 Title/body에 따라서 오는데, 포그라운드 알림은 데이터가 텅 비어 있는 것처럼 보인다. 내용물을 전달하려면 Title/body가 아니라,  추가 옵션에서 key:value를 추가해서 보내면 된다.

 

이제 fcm으로 메세지를 보내는 서버를 구현해야한다.

먼저 firebase 내 프로젝트 설정 페이지에서 키를 만든다.
그리고 아래의 python 파일을 새롭게 만들고, 키 파일의 경로를 입력한다.

 

fcm_messaging.py

import firebase_admin
from firebase_admin import credentials
from firebase_admin import messaging
from firebase_admin import firestore
cred = credentials.Certificate("키 파일 경로")
default_app = firebase_admin.initialize_app(cred)
db = firestore.client()
doc_ref = db.collection("UserTokens").document("User")
registration_token = doc_ref.get().to_dict()['token']
message = messaging.Message(
    notification=messaging.Notification(
    title="테스트 제목",
    body="테스트 내용",
),
    data={
        'score': '8501',
        'time': '2:45',
    },
    token=registration_token,
)
response = messaging.send(message)
print('Successfully sent message:', response)

간단히 설명하면 DB에 저장된 fcmToken을 불러온 뒤, 그쪽으로 메세지를 송신한다. 
쓰임새에 따라 함수로 만들어서 원하는 알고리즘에 집어넣으면 된다.

+ Recent posts