최근 Firebase push notification을 테스트해볼 일이 생겨서 간단한 안드로이드 앱을 만든 뒤 해당 앱으로 정상적으로 push notification이 전달되는 지 확인해봐야할 일이 생겼다.
그냥 간단하게 만들고 싶어서 flutter 쪽을 살펴봤는데 (개인적인 견해이지만) flutter는 코드의 양이 생각보다 많다는 느낌이 들었다. 그리고 굉장히 익숙하지 않은 형태처럼 느껴졌다.
예시 코드를 찾아보다가 그냥 이럴 바에 kotlin이나 java로 안드로이드 앱을 간단하게 만드는 게 낫다고 생각했다.
순서는 간단하다.
아래 순서대로만 진행하면 된다.
- Firebase 콘솔에 접속해서 Firebase project를 만들어 준다.
- project내에서 Android app을 만들어주고 google-services.json 파일을 다운받는다.
- project 내에서 firebase cloud messaging을 허용하게끔 설정해주자. FCM이라고도 불린다.
- push notification을 받을 앱을 로컬 환경에서 간단하게 만든다. (안드로이드 스튜디오를 설치해서 간단하게 만들어볼 수 있다.)
- 안드로이드 스튜디오에서 만든 프로젝트의 module의 app 폴더에 google-services.json파일을 추가해준다.
- build.gradle에 필요한 의존성을 받아준다. (firebase 콘솔에서 확인할 수 있다)
- 안드로이드 app을 구현하고 빌드해보고 Run app을 눌러서 구동해보자.
- 이후 FCM에서 인앱메시지를 하나 만들어서 보내보자.
- 안드로이드 app에 찍히는 게 확인되면 성공이다.
- 참고로 firebase credential json 파일을 firebase 콘솔에서 받아놓은 상태에서 테스트를 진행해야 하는데 push notification 요청을 발생시킬 주체가 이 credential json 파일을 들고 있으면 된다.
나는 airflow에서 task가 돌면서 자동으로 firebase push notification을 보내주도록 만들고 싶었다.
참고로 airflow에서는 pip install google-cloud-firestore을 받아주자. (참고로 google-cloud쪽이 버전 이슈가 좀 있을 수 있다. 이게 특히 apache-airflow랑 버젼 이슈가 좀 있는데 pip3 install firebase-admin을 통해서 firebase를 쓸 때 도 google-cloud와 함께 버전 이슈가 발생한다. 내 경우는 몇 가지 패키지를 수동으로 다운그레이드 해줬다.)
만약 airflow task를 작성해준다면 다음 예시를 참고해서 작성하자.
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
default_args = {
'owner': 'airflow',
'start_date': datetime(2022, 1, 1),
}
dag = DAG(
'firebase_notification_dag',
default_args=default_args,
description='Send a Firebase push notification',
schedule_interval=timedelta(days=1),
catchup=False
)
from google.cloud import firestore
from google.oauth2 import service_account
def send_push_notification():
# Load the Google service account credentials from a JSON file
credentials = service_account.Credentials.from_service_account_file("path/to/your/firebase-adminsdk-credentials.json")
# Initialize Firestore with the service account credentials
firestore_client = firestore.Client(credentials=credentials)
# Get the registration token of your test device (you'll need to store this in Firestore from your app)
registration_token = firestore_client.collection("devices").document("test_device").get().get("registrationToken")
# Send the push notification
from google.cloud import messaging
messaging_client = messaging.Client(credentials=credentials)
message = messaging.Message(
notification=messaging.Notification(
title="Test Notification",
body="This is a test notification from Airflow.",
),
token=registration_token,
)
response = messaging_client.send(message)
print(f"Sent message: {response}")
send_notification_task = PythonOperator(
task_id='send_push_notification',
python_callable=send_push_notification,
dag=dag
)
여기서 path/to/your/firebase-adminsdk-credentials.json을 firebase console에서 다운로드 받은 firebase service account json 파일 경로로 바꿔주자.
이제 아래 안드로이드 코드를 작성해주고 실행시켜보자.
import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.firestore.FirebaseFirestore
// ...
val firestore = FirebaseFirestore.getInstance()
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w("MainActivity", "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}
// Get the registration token and store it in Firestore
val token = task.result
val deviceData = hashMapOf("registrationToken" to token)
firestore.collection("devices").document("test_device").set(deviceData)
.addOnSuccessListener {
Log.d("MainActivity", "Device registration token stored in Firestore")
}
.addOnFailureListener { e ->
Log.w("MainActivity", "Error storing device registration token in Firestore", e)
}
})
생각보다 잘 돌아간다.
오늘 작성한 글은 생략된 부분들이 많다. 요즘 시간이 없어서 급하게 글을 쓰는 중인데 두서없지만 일단은 대략적인 흐름만 파악하기 위해 적어뒀다.
작성된 글을 그대로 따라하면 분명 중간에 자잘한 이슈가 생길텐데 그냥 정리해놓은 흐름만 보시고 나머지는 간단하게 서치하셔서 진행하시면 될 것 같다.
아래 링크에서 많은 도움을 받았다.
감사합니다.
https://firebase.google.com/docs/cloud-messaging/concept-options?hl=ko