huzit
___을 입력해주세요
huzit
전체 방문자
  • 분류 전체보기 (137)
    • 안드로이드(Compose) (10)
      • UI (4)
      • 개념 (6)
    • 안드로이드 (50)
      • 기본개념 (6)
      • 응용 (4)
      • Debug (18)
      • Binding (3)
      • RecyclerView (5)
      • Firebase (6)
      • Retrofit (1)
      • Activity & Fragment (4)
    • 코틀린 (22)
    • 코딩테스트 (38)
      • 백준 (10)
      • 프로그래머스 (28)
    • 일상 (6)
    • CS 지식 (4)
    • 라즈베리파이 (7)

블로그 메뉴

  • 홈
  • 태그
  • 글쓰기
  • 관리

공지사항

인기 글

태그

  • firebase
  • Retrofit
  • compose
  • RecyclerView
  • 공돌카돈
  • 브레빌 밤비노 플러스
  • IFTTT
  • 프로그래머스
  • Java
  • recyclerView ClickEvent
  • jetpack
  • gts4mini
  • Kotlin
  • 라즈베리 파이
  • FCM
  • docker
  • Debug
  • Android
  • 공돌이파파
  • 코틀린

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
huzit

___을 입력해주세요

[FCM] FirebaseCloudMessaging API 만들기
안드로이드/Firebase

[FCM] FirebaseCloudMessaging API 만들기

2022. 11. 12. 01:58
728x90

이번엔 메시지 API를 만들어서 Postman을 통해 토큰과 타이틀, 바디를 보내 폰으로 알림을 받는 과정을 정리해보려 합니다. Firebase프로젝트를 생성하는 과정은 이전 게시글을 참고하시면 됩니다.

 

[FCM]Firebase Cloud Messaging 수신하기

Android에서 Firebase 클라우드 메시징 클라이언트 앱 설정 Firebase Summit에서 발표된 모든 내용을 살펴보고 Firebase로 앱을 빠르게 개발하고 안심하고 앱을 실행하는 방법을 알아보세요. 자세히 알아보

huzit.tistory.com

시작하기 전

어느 정도 배웠던 기억을 살려서 구현한 거라 최신 빌드에 맞지 않을 수 있습니다. 참고 정도로만 보시는 걸 추천드려요.


Springboot 프로젝트 생성

Project Initializer

프로젝트를 생성할 때 언어는 코틀린, 빌드 툴은 Gradle로 해줬습니다. 언어와 빌드 툴은 안드로이드와 동일하게 진행하겠습니다. 

의존성은 롬복과 SpringWeb 정도만 추가해줍니다. 


Firebase SDK 설치

프로젝트 빌드가 완료되었다면 한 번 실행해준 뒤 FirebaseSDK를 설치해줍니다.

콘솔

키를 넣을 패키지를 만든 후 알기쉬운 이름으로 변경해서 넣어줍니다.

이제 프로젝트의 build.gradle.kts로 가서 의존성을 추가해줍니다.

//FirebaseSDK
implementation("com.google.firebase:firebase-admin:9.1.1")
//OkHttp
implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.10")
//jackson
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

http통신을 이용해야하므로 OkHttp의 의존성도 추가해주고 Jackson 어노테이션을 하나 쓸 것이므로 같이 해줍니다.

여기까지가 프로젝트 설정입니다. 절반 왔네요

기능 구현에 앞서 앞으로 해야할 것을 정리하자면

  • FCMService 클래스 작성
  • 통신을 위한 DTO 작성
  • Controller작성 

이 있습니다. 간단한 것 부터 시작해보죠.


DTO 작성

 

FCM 메시지 정보  |  Firebase 클라우드 메시징

Firebase Summit에서 발표된 모든 내용을 살펴보고 Firebase로 앱을 빠르게 개발하고 안심하고 앱을 실행하는 방법을 알아보세요. 자세히 알아보기 이 페이지는 Cloud Translation API를 통해 번역되었습니

firebase.google.com

우리가 보내야 하는 메시지는 단순 알림 메시지이며 JSON 형식은 다음과 같습니다. (다른 메시지는 위 링크에서 확인할 수 있습니다)

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
  }
}

메시지 안에 토큰, 알림(타이틀, 내용) 이 들어가 있는 구조입니다.

따라서 Message와 Notification 데이터 클래스를 만들어줍니다. 

@JsonIgnoreProperties(ignoreUnknown = true)
data class FCMMessage(
    var message: Message,
    var validate_only: Boolean = false,
){
    data class Message(
        var token: String = "",
        var notification: Notification,
    )

    data class Notification(
        var title: String = "",
        var body: String = "",
        var image: String = "",
    )
}

@JsonIgnoreProperties(ignoreUnknown = true) 어노테이션으로 데이터 클래스에 선언되지 않은 프로퍼티에 맵핑이 되면 예외를 발생시키지 말고 무시하도록 만듭니다. 

이제 Request로 부터 보낼 대상의 토큰, 타이틀, 내용을 받을 데이터 클래스가 필요합니다. 

data class RequestDTO(
    val targetToken: String,
    val title: String,
    val body: String
)

Controller에서 RequestBody를 통해 받기 위함이므로 RequestDTO 만들어줍니다.


FCM Service 클래스 작성

서비스 클래스의 메서드는 3가지 입니다.

getAccessToken()

자격 증명을 이용하여 액세스 토큰을 발행하는 메서드입니다.

@Service
class FCMService{
 ...
     @Autowired
    lateinit var resourceLoader: ResourceLoader
	
    @Throws(IOException::class)
    private fun getAccessToken(): String{
//        val firebaseConfigPath = "src/main/resources/serviceKey/firebaseServiceKey.json"
//        val inputStream = FileInputStream(firebaseConfigPath)
        val firebaseConfigPath = "classpath:/serviceKey/firebaseServiceKey.json"
        val inputStream = resourceLoader.getResource(firebaseConfigPath).inputStream

        val googleCredentials = GoogleCredentials
            .fromStream(inputStream)
            .createScoped(listOf("https://www.googleapis.com/auth/cloud-platform"))
        googleCredentials.refreshIfExpired()
        return googleCredentials.accessToken.tokenValue
    }
}

createScoped에는 Google API의 OAuth 2.0 범위를 위한 스코프를 입력해야 합니다.

 

Google API의 OAuth 2.0 범위  |  Authorization  |  Google Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English 의견 보내기 Google API의 OAuth 2.0 범위 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이

developers.google.com

참고할 내용이 많아요

우리가 필요한 건 FirebaseCloudMessaging이므로 둘 중 하나를 넣어주면 됩니다.

여기서 의문점이 하나 생깁니다. "주석은 왜 했지?"

//        val firebaseConfigPath = "src/main/resources/serviceKey/firebaseServiceKey.json"
//        val inputStream = FileInputStream(firebaseConfigPath)
        val firebaseConfigPath = "classpath:/serviceKey/firebaseServiceKey.json"
        val inputStream = resourceLoader.getResource(firebaseConfigPath).inputStream

두 코드의 차이는 절대 경로 / 상대 경로 , FileInputStream / resourceLoader입니다.

일단 FileInputStream에 대해 간단히 설명하자면 하드 디스크 상에 존재하는 파일로부터 바이트 단위를 입력받는 클래스입니다. 여기서 하드 디스크가 가장 중요합니다.

저는 Docker를 통해 라즈베리 파이로 배포할 생각이기 때문에 .jar로 압축해야 합니다. 하드 디스크가 아니라 jar에서 읽어야 합니다.

그래서 FileInputStream이 아니라 ResourceLoader를 통해 읽고 있는 것입니다. 

또한 주석처럼 절대 경로를 넣게 되면 파일 자체를 찾을 수 없으므로 classpath를 이용해서 상대 경로로 넣어줬습니다

makeMessage()

@Service
class FCMService{
 	...
    //메시지 생성
    private fun makeMessage(targetToken: String, title: String, body: String): String{
        val notification = FCMMessage.Notification(title, body)
        val message = FCMMessage.Message(targetToken, notification)
        val fcmMessage = FCMMessage(message = message)
        val objectValue = jacksonObjectMapper().writeValueAsString(fcmMessage)

        return objectValue
	}
}

앞서 생성한 데이터 클래스에 맞춰서 객체를 만들어 주면 됩니다. jacksonObjectmapper를 통해 생성한 FCMMessage객체를 JSON형식으로 변경해줍니다.

sendMessageTo()

@Service
class FCMService{
    private val SERVER_ENDPOINT = "https://fcm.googleapis.com/v1/projects/내 파베 프로젝트 ID/messages:send"
	...
    //메시지 전송
    @Throws(IOException::class)
    fun sendMessageTo(targetToken: String, title: String, body: String){
        lateinit var response: Response
        try {
            val message = makeMessage(targetToken, title, body)
            val requestBody = message.toRequestBody("application/json; charset=utf-8".toMediaType())
            val request = Request.Builder()
                .url(SERVER_ENDPOINT)
                .post(requestBody)
                .addHeader(HttpHeaders.CONTENT_TYPE, "application/json; UTF-8")
                .addHeader(HttpHeaders.AUTHORIZATION, "Bearer ${getAccessToken()}")
                .build()
            response = OkHttpClient().newCall(request).execute()
            println(response.body.toString())
        } finally{
            response.body.close()
        }
    }
    ...
}

서버 엔드포인트로 앞서 생성한 파이어 베이스 프로젝트 id를 지정해주면 됩니다.

프로젝트 이름인 줄 알았는데 ID였답니다 ㅎ

 

Controller

컨트롤러 차례입니다.

@RestController
@RequiredArgsConstructor
class NotificationController {
    @Autowired
    val fCMService = FCMService()

    @Throws(IOException::class)
    @PostMapping("/sendNotification")
    fun sendNotification(@RequestBody requestDTO: RequestDTO): ResponseEntity<String> {
        fCMService.sendMessageTo(requestDTO.targetToken, requestDTO.title, requestDTO.body)
        return ResponseEntity.ok().build()
    }

    @GetMapping("/{testValue}")
    fun test(@PathVariable(name = "testValue") test : String): String{
        return "testvalue is $test"
    }
}

실행

이제 실행해봅시다. 로컬에서 테스트하므로 Postman을 설치해줘야 합니다. 

Postman

Get은 정상적으로 작동되는 것을 볼 수 있습니다. 이제 Post로 보내볼 차례입니다.

PPPostman

우리가 RequestDto에서 작성한 대로 Body를 작성해줘야 합니다. getAccessToken()으로 발급한 토큰을 넣어주면 됩니다.

이제 토큰 발급한 기기를 보면 알림이 온 것을 확인할 수 있습니다. 

이놈의 알림 하나때문에!

만약 알림이 오지 않는다면 앱을 껐다 켜보거나 알림에서 알림 일시중지 무시를 해 보시면 됩니다.

마치며

만약 도커에 올려서 배포하고 싶다면 아래 게시글을 참고하시면 됩니다.

 

[docker]kotlin + SpringBoot를 Docker Hub에 올리기(feat.FCM)

1. 스프링 부트 프로젝트 만들기 빌드 툴은 gradle이므로 build.gradle.kts에 spring-boot-starter-web 의존성을 추가하고 테스트할 수 있는 맵핑을 하나 만들어주면 됩니다. @RestController @RequiredArgsConstructor clas

huzit.tistory.com

다음은 Retrofit2를 이용해서 RestAPI 통신하는 어플 제작 과정을 올리겠습니다.

참고

 

[SpringBoot] FCM을 통해 Push알림 보내보기

( + 진행 당시, 기능 구현에 집중하다보니 전체적인 설계나 코드가 클린하지 못할 수 있으니 이 부분은 리팩토링 하면서 적용하시면 좋을 것 같아요! :) ) 현재 참여하고 있는 IT연합 동아리 YAPP에

sol-devlog.tistory.com

728x90
저작자표시 (새창열림)

'안드로이드 > Firebase' 카테고리의 다른 글

Firebase Crashlytics 시작하기  (0) 2023.04.14
Firebase 시작하기  (0) 2023.04.14
[FCM] Retrofit2로 API통신하기  (0) 2022.11.16
[FCM]Firebase Cloud Messaging 수신하기  (0) 2022.11.11
파이어베이스로 구글 소셜로그인  (0) 2022.06.13
    '안드로이드/Firebase' 카테고리의 다른 글
    • Firebase 시작하기
    • [FCM] Retrofit2로 API통신하기
    • [FCM]Firebase Cloud Messaging 수신하기
    • 파이어베이스로 구글 소셜로그인
    huzit
    huzit
    simple is best

    티스토리툴바