티스토리 뷰

SPRING

SpringBoot 와 FCM 연동

MC's Father 2019. 4. 16. 15:22

1. Architecture

스프링 서버를 통해 데이터를 앱에 전달 하는 형태로 개발

 

2. HTTP POST

 

단일 데이터의 경우

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=SERVER_KEY
{
 "to":"token value",
 "notification" : {
    "title" : "TITLE",
	"body" : "BODY"
 },
 "data" : {
	"Key-1" : "Value 1",
	"Key-2" : "Value 2"
 },
}

 

항목에 등록된 장치로 데이터 보내는 경우

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=SERVER_KEY
{
  "condition": "'ABC' in topics || 'XYZ' in topics",
  "data": {
      ...
   }
}

 

여러 장치에 데이터를 보내는 경우

https://fcm.googleapis.com/fcm/send
Content-Type : application/json
Authorization : key = SERVER_KEY
{
    "registration_ids" : ["token value1", ... ]
    "notification" : 
    {
        "title" : "value"
        "body" : "value"
    }
}

결과 값 

// Success:
{
  "message_id": "123456"
}
 
// failure example:
{
  "error": "TopicsMessageRateExceeded"
}

3. Structure

각 사용자마다 위치는 다를 수 있습니다.

4. POM.XML 추가

<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20180813</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.firebase/firebase-admin -->
<dependency>
    <groupId>com.google.firebase</groupId>
    <artifactId>firebase-admin</artifactId>
    <version>6.8.0</version>
</dependency>

5. 서버 설정

HeaderRequestInterceptor 생성

import java.io.IOException;
 
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
 
public class HeaderRequestInterceptor implements ClientHttpRequestInterceptor {
 
  private final String headerName;
  private final String headerValue;
 
  public HeaderRequestInterceptor(String headerName, String headerValue) {
    this.headerName = headerName;
    this.headerValue = headerValue;
  }
 
  @Override
  public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
      throws IOException {
    HttpRequest wrapper = new HttpRequestWrapper(request);
    wrapper.getHeaders().set(headerName, headerValue);
    return execution.execute(wrapper, body);
  }
}

AndroidPushNotificationsService 생성

import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
 
import org.springframework.http.HttpEntity;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
 
@Service
public class AndroidPushNotificationsService {
 
  private static final String FIREBASE_SERVER_KEY = "Your Server Key here!";
  private static final String FIREBASE_API_URL = "https://fcm.googleapis.com/fcm/send";
  
  @Async
  public CompletableFuture<String> send(HttpEntity<String> entity) {
 
    RestTemplate restTemplate = new RestTemplate();
 
    /**
    https://fcm.googleapis.com/fcm/send
    Content-Type:application/json
    Authorization:key=FIREBASE_SERVER_KEY*/
 
    ArrayList<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
    interceptors.add(new HeaderRequestInterceptor("Authorization", "key=" + FIREBASE_SERVER_KEY));
    interceptors.add(new HeaderRequestInterceptor("Content-Type", "application/json"));
    restTemplate.setInterceptors(interceptors);
 
    String firebaseResponse = restTemplate.postForObject(FIREBASE_API_URL, entity, String.class);
 
    return CompletableFuture.completedFuture(firebaseResponse);
  }
}

Controller 생성

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
 
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import com.javasampleapproach.fcm.pushnotif.service.AndroidPushNotificationsService;
 
@RestController
public class WebController {
 
  private final String TOPIC = "JavaSampleApproach";
  
  @Autowired
  AndroidPushNotificationsService androidPushNotificationsService;
 
  @RequestMapping(value = "/send", method = RequestMethod.GET, produces = "application/json")
  public ResponseEntity<String> send() throws JSONException {
 
    JSONObject body = new JSONObject();
    body.put("to", "/topics/" + TOPIC);
    body.put("priority", "high");
 
    JSONObject notification = new JSONObject();
    notification.put("title", "JSA Notification");
    notification.put("body", "Happy Message!");
    
    JSONObject data = new JSONObject();
    data.put("Key-1", "JSA Data 1");
    data.put("Key-2", "JSA Data 2");
 
    body.put("notification", notification);
    body.put("data", data);
 
/**
    {
       "notification": {
          "title": "JSA Notification",
          "body": "Happy Message!"
       },
       "data": {
          "Key-1": "JSA Data 1",
          "Key-2": "JSA Data 2"
       },
       "to": "/topics/JavaSampleApproach",
       "priority": "high"
    }
*/
 
    HttpEntity<String> request = new HttpEntity<>(body.toString());
 
    CompletableFuture<String> pushNotification = androidPushNotificationsService.send(request);
    CompletableFuture.allOf(pushNotification).join();
 
    try {
      String firebaseResponse = pushNotification.get();
      
      return new ResponseEntity<>(firebaseResponse, HttpStatus.OK);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
 
    return new ResponseEntity<>("Push Notification ERROR!", HttpStatus.BAD_REQUEST);
  }
}

 

Firebase 를 이용한 Push 처리시 발생되는 Background 이슈로 인해서 작은 작업이 필요함.

1) 서버 또는 콘솔에서 전달되는 데이터에 'Notification'키로 설정되는 데이터를 없애거나,

2) 'Notification'키 내에 Intent 필터를 걸어 줄수 있는 액션을 함께 내려 준다.

 

ex)

Notification 키가 포함되어 내려오는 경우

{
	"registration_ids": ["단말 토큰 키"],
	"notification" : {
    	"title": "타이틀",
        "body": "바디"        
    },
    "data" : {
    	"timestamp" : 123415165432
   	}
}

Notification 키를 없애는 형태

{
	"registration_ids": ["단말 토큰 키"],
	"data" : {
        "title": "타이틀",
        "body": "바디"   
    	"timestamp" : 123415165432
   	}
}

 

 

참고 : https://grokonez.com/spring-framework/spring-boot/firebase-cloud-messaging-server-spring-to-push-notification-example-spring-boot

 

Firebase Cloud Messaging - Spring Server to Push Notification Example | Spring Boot - grokonez

Create a Spring Boot Application Server that can make message and push notification to Android Client via Firebase - firebase cloud messaging server Spring.

grokonez.com

참고 : https://layers7.tistory.com/46

 

[Android] FCM Background Push 이슈 대응 방법

이번 포스팅에서는 Firebase를 이용한 Push 처리 시 발생되는 Background 이슈에 대해 기술한다. Foreground? Background? Firebase를 이용한 Push처리시에 대부분이 콘솔 혹은 포스트맨을 통해 간략한 테스트 후..

layers7.tistory.com

 

'SPRING' 카테고리의 다른 글

SPRING BOOT SSO 자료 정리  (31) 2020.11.05
properties와 value 사용시 static 변수의 연결  (63) 2019.03.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함