android fcm background ( killed ) notification / 앱이 활성화 안되어 있을 때도 알림 받기

북마크 추가


앞서 적용한 push notification을 firebase console에서 테스트 해보면 앱이 비활성화 되어 있는 상태에서는 FirebaseMessagingService 의 onMessageReceived를 타지 않습니다.

 

 

 

10:22 분은  앱이 비활성화 된 상태에서 보낸 알림이고

10:23 분은 앱이 활성화 된 상태에서 보낸 알림입니다.

 

onMessageReceived에 해놓은 설정이 적용되지 않는 것을 확인 할 수 있습니다.

 

해결 방법

 

앱이 백그라운드에서 실행중이거나 죽어있을때 적용 하려면 fcm api를 직접 호출 해 주면 됩니다.

 

api url :: https://fcm.googleapis.com/fcm/send

 

node.js 를 통해 api를 호출하는걸 예로 들겠습니다.

 

 

function sendTopicMessage(title, content, imgUrl, link) {
        var message = { title : title , content : content, imgUrl : imgUrl , link : link }
        request({
                url : 'https://fcm.googleapis.com/fcm/send',
                method : 'POST',
                headers : {
                        'Content-Type' : ' application/json',
                        'Authorization' : 'key=Firebase API KEY'
                },
                body : JSON.stringify({
                        "data" : {
                                "message" : message
                        },
                        "to" : "/topics/notice"
                })
        }, function(error, response, body) {
                if (error) {
                        console.error(error, response, body);
                } else if (response.statusCode >= 400) {
                        console.error('HTTP Error: ' + response.statusCode + ' - '
                                        + response.statusMessage + '\n' + body);
                } else {
                        console.log('Done')
                }
        });

 

url은 'https://fcm.googleapis.com/fcm/send' method = POST 방식 , json 타입으로 설정하였습니다.

header에는 Authorization을 꼭 넣어 주셔야 합니다. Firebase API KEY에는 발급 받으신 api key를 넣어줍니다.

 

 

body의 to는 보낼 대상으로 /topic/토픽명 으로 하게 되면 해당 토픽 전체 사용자에게 메세지를 발송 합니다.

 

ex) FirebaseMessaging.getInstance().subscribeToTopic("notice");

 

/topic 대신에 사용자별 토큰 값을 넣게 되면 특정 사용자에게만 보낼 수 있습니다.

 

ex)

String token = FirebaseInstanceId.getInstance().getToken();

 

android 프로젝트에서 저렇게 하면 사용자 token값을 얻어 올 수 있고 그 값이

 

fmPgYSi3Iww:APA91bHKi23li9Kn1YKPiSTX4cfdwJ4BBjTHHRvhZBYnz4Rw2aKWgLYNgTKGJX2-tmjoZRib0XonkxL34yQk-O_pplT-mR46dd3l04NL1BCW3D47dd2Ra87ejktW1ju6FUw_AUZrndb9wt

 

위와같이 나오는데 저 값을 to 에 넣으면 해당 사용자 에게 푸시알림 발송이 가능합니다.

 

"to" : "fmPgYSi3Iww:APA91bHKi23li9Kn1YKPiSTX4cfdwJ4BBjTHHRvhZBYnz4Rw2aKWgLYNgTKGJX2-tmjoZRib0XonkxL34yQk-O_pplT-mR46dd3l04NL1BCW3D47dd2Ra87ejktW1ju6FUw_AUZrndb9wt"


------------------------------


fcm messaging api를 사용해서 보내게 되면 앱이 background에서 실행 중이거나 kill 되어 있을때에도 onMessageReceived를 타는것을 확일 할 수 있습니다.


* 위 코드의 var message는 제 프로젝트에 맞춰 놓은거라 각자 프로젝트에 맞게 쓰시면 됩니다.​ 


 

 

+ 내용 추가 2017-01-13

 

postman으로 테스트 할 경우 파라미터 세팅

 


 

1. 상단 POST , fcm URL 입력

2. headers 탭에 content-Type 과 authorizatino 추가 (api key값은 지웠습니다)

 


 

3. body에 JSON 형식으로 위와같이 적고 raw 선택 오른쪽에서 타입은 JSON을 선택 합니다

4. Send를 누르면  테스트 가능합니다.

 

OkHTTP Generator 결과

 

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");

RequestBody body = RequestBody.create(mediaType, "{\"data\" : {\"message\" : {\"title\":\"test\",\"content\":\"testcontent\",\"imgUrl\":\"\",\"link\":\"\"}},\"to\" : \"/topics/noticeMsg\"}");

Request request = new Request.Builder()

    .url("https://fcm.googleapis.com/fcm/send")

    .post(body)

    .addHeader("content-type", "application/json") 

    .addHeader("authorization", "key=api키") 

    .addHeader("cache-control", "no-cache")

    .addHeader("postman-token", "postman토큰")

    .build();

Response response = client.newCall(request).execute(); 

 

+ 내용 추가

 

java에서 firebase messaging api 호출 하는 방법 추가 했습니다

 

LINK :: http://trandent.com/board/Android/detail/764

 

AD
관리자
2016-07-21 11:05
SHARE
댓글

아 제가 말씀드린 부분은 data.message의 내용 이었는데  해결하셨다니 다행입니다ㅎㅎ
관리자

해결햇습니다 ㅜㅜ 
그냥  var obj = new Object();

               obj.title = 'testtitle';
               obj.content = 'testcontent';
               obj.imgUrl = 'testimgUrl';
               obj.link = 'testlink';
        var message = JSON.stringify(obj);

부분에   obj.to = "/topics/notice";  하니까 되네요 ;; 따로 써줘야는건줄알고 .. 하하..  만들다 또 막히면 질문드릴게요 감사합니다!
킴***

답변 감사드려요  말씀 주신데로 자바스크립트 아작스로 해보았는데 
        var obj = new Object();

               obj.title = 'testtitle';
               obj.content = 'testcontent';
               obj.imgUrl = 'testimgUrl';
               obj.link = 'testlink';
        var message = JSON.stringify(obj);
        
$.ajax({
                type: 'POST',
        url: 'https://fcm.googleapis.com/fcm/send',
        beforeSend : function(xhr){
            xhr.setRequestHeader("Authorization", "key=");
            xhr.setRequestHeader("Content-type","application/json");
        },
        data : message,
            success : function(data) {       
            },error : function(data,xhr){
                }
        })
         이때 400 에러가 뜨더라구요 포스트맨은 Error=MissingRegistration 이렇게 에러가 뜨고 아마도    "to" : "/topics/notice" 이부분이 빠진거같은데 위소스에 어디부분에 그걸 넣어야 할까요 ㅜ
킴***

ajax로 fcm에 다이렉트로 쏘게 되면 
{ title : "타이틀내용" , content : "본문내용", imgUrl : "http://~~~" , link : "http://@@@@@" }  
이런식으로 데이터를 넣어서 보냈다면
firebaseMessagingService에서 받아서 jsonobject로 변환 후 꺼내서 쓰셔야 될 것 같습니다.
H**

안녕하세요 자바스크립트로 하시려면
 request({
                url : 'https://fcm.googleapis.com/fcm/send',
                method : 'POST',
                headers : {
                        'Content-Type' : ' application/json',
                        'Authorization' : 'key=Firebase API KEY'
                },
                body : JSON.stringify({
                        "data" : {
                                "message" : message
                        },
                        "to" : "/topics/notice"
                })
        }, function(error, response, body) {
              
        });
위 코드를 ajax 형태로 바꾸면 동작할것으로 생각됩니다.
$.ajax({
	type: 'POST',
        url: '',
        data: ,
        dataType : 'json',
	    success : function(data) {	     
	    },error : function(data){}
	})
H**

아 그리고 또 문제가있는게 노드로 해서 안되서 포스트맨으로 위에올려주신거대로 햇는데 메세지 부분에 
{ title : title , content : content, imgUrl : imgUrl , link : link }  이게 그대로 찍혀나오더라구요  푸쉬 부분에 ㅜㅜ 
타이틀은 Push Title  이걸로오고 FirebaseMessagingService 이부분에 수정해야할게있나요?
킴***

안녕하세요 잘 배우고있습니다 근데 문제가 좀 생겨서 질문좀 드릴게요 ㅜ 
글중에 node.js 로 함수선언하신다음에 보내는부분이있는데요 
노드는 제가 정확하게 잘알지를못해서 문제가 좀 생겻습니다 노드는 일단 작동되도록 설치는 다되어있구요 
파일을 notice.js 로 생성해서 위에 소스를 그대로 넣고 실행시켜봣는데요 



      request({
        ^

ReferenceError: request is not defined
    at sendTopicMessage (/web_root/nodejs/notice.js:5:9)
    at Object. (/web_root/nodejs/notice.js:33:1)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Function.Module.runMain (module.js:701:10)
    at startup (bootstrap_node.js:193:16)
    at bootstrap_node.js:617:3
이러한 에러가 뜨더라구요  node는 처음인데 혹시 request 가 모듈같은거일까요? 모듈을 설치해야하는 문제인걸까요 혹시 .. ㅎㅎ

아니면 혹시 자바스크립트버전으론 api 할수없을까요 ..
킴***

OkHttpGenerator 라고 작성한 부분은 자바에서 OkHttpClient 라이브러리를 이용해서 fcm api를 호출 하여 푸시알림을 보내는 부분입니다.
관리자

OkHTTP Generator 결과 이건 어디서 처리하는거죠?
초보라서 따라가기도 어렵네요 ㅎㅎ 포스트맨으로 테스트 한번 해볼려는데 실행 시 아래에 
{
    "message_id": 1234567890 
}

이런것만 출력되고 어플에 메세지는 오지 않습니다.
임**

백그라운드 푸시처리하는데 많은 도움이 되었습니다
정말 감사합니다
윤**

혹시 프로세스 강제종료시도 알림 오는 방법 아시나요??


앱이 종료시켰을때는 알림이 오는데 프로세스를 강제종료시켰을때는 별도 처리가 필요할듯 합니다 내용은 파싱해서 사용하시면 됩니다
H**

백그라운드 때는 잘 들어오는데 kill 일떄는 안들어오네요 ㅠㅠ 뭔가 따로 해줘야되나요?? 
그리고 알림 내용이 json그대로 들어오는데 잘라서 sendnotification에 넣어야 되나요?


크헉.. authorization 의 value 는 API KEY가 아니라 Server Key 네염..ㅋ
전송되는거 확인했습니다 ㅎㅎ
J**********

pushman 을 사용해서 위와 같이 보낼 경우 401  에러가 발생합니다.. 헤더쪽에 말씀하신대로 content-Type 과 authorization 정의해줬구여
authorizatino 의 value 값은 key=AlzaSy..으로 제쪽 firebase의 API Key를 갔다 넣었구여
왜 그럴까여..?
J**********

답변 감사합니다. 
일단 핑거푸시로 진행 중 이였는데 그쪽도 초보에맞는 가이드가 없어서 포기 하려구요. 
그냥 한규호님이 올려주신 FCM으로만 사용해야 할것 같네요. 
좋은 포스팅 감사했었습니다. 항상 건승하세요. 
나중에 시간 되시면 관련 포스팅 기대 하겠습니다.
C**

private void sendPost() throws Exception {
		String url = "https://fcm.googleapis.com/fcm/send";
		URL obj = new URL(url);
		HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();		
		con.setRequestMethod("POST");
		con.setRequestProperty("content-type", "application/json");
		con.setRequestProperty("authorization", "key=api키");
		String urlParameters = "{\"data\" : {\"message\" : {\"title\":\"test\",\"content\":\"testcontent\",\"imgUrl\":\"\",\"link\":\"\"}},\"to\" : \"/topics/noticeMsg\"}";
		// Send post request
		con.setDoOutput(true);
		DataOutputStream wr = new DataOutputStream(con.getOutputStream());
		wr.writeBytes(urlParameters);
		wr.flush();
		wr.close();

		int responseCode = con.getResponseCode();
		System.out.println("\nSending 'POST' request to URL : " + url);
		System.out.println("Post parameters : " + urlParameters);
		System.out.println("Response Code : " + responseCode);

		BufferedReader in = new BufferedReader(
		        new InputStreamReader(con.getInputStream()));
		String inputLine;
		StringBuffer response = new StringBuffer();

		while ((inputLine = in.readLine()) != null) {
			response.append(inputLine);
		}
		in.close();

		//print result
		System.out.println(response.toString());

	}
이런식으로 하면 될거 같긴 한데 테스트는 못해봤습니다.
net.sf.json을 사용 중이시라면 파라미터를 JSONObject로 만들어서 보내도 될거같습니다.
H**

참 자바스트립트 때문에 버철스튜디오? 그것도 깔아서 해보려 했으나,
끝까지 포스팅 한 곳이 없어 지식이 부족한 저에게는 너무 어렵더라구요.
염치 불구 하고 이렇게 문의 하는 것은, 포스팅을 쭉 쫒아 왔고 그래서 기본 코딩이,
이 블러그와 일치합니다. 그래서 더욱 더 이곳에성의 가르침을 원합니다.
구글링으로는 조각조각 나눠져 있었서 저의 지식으로는 이해가 부족합니다.
겨우 안드로이드 만 조각을 대충 맞출 수 있는 단계에 있습니다. 다시한번 부탁드립니다.
C**

자바로 구현하는 방법은 어떻게 해야 하는 건가요?
구글링으로 아무리해도 무지해서인지... 너무 힘드네요.
대체적인 의견이 앱자체에서는 공지시 깨울수 없다고 하더라구요.
그래서 이렇게 염치 불구하고 자세한 포스팅을 부탁드립니다.
C**

포스트맨은 테스트 용도로 사용하는 툴 입니다
푸시알림 전송은 어플과 관계없이 따로 fcm api를 호출하도록  구현해야 됩니다.
저의 경우는 자바스크립트로 만들어져 있습니다
H**

POSTMAN 관련해서 더 자세한 포스팅 부탁 해도 될까요?
최근에 배우기 시작해서 겨우 웹뷰로 어플 잘따라 가고 있었으나,
포스트맨에서 걸리고 있습니다. 사실 푸시라는게 앱이 꺼져 있는 상태에서 
발송 즉 발송 알림음이 안 된다면 의미가 없는 것 같아서 이렇게 부탁드립니다. ㅠㅠ
C**

넵 해결 하시면 꼭 알려주세요
H**

빠른 답변 감사합니다, Kyuho Han님.
링크에 설명된 방법으로 시도해 보겠습니다. 좋은 결과가 있으면 다시 포스트 할께요. ^^
S************

박진현님 위에 글에 나와 있듯이 fcm api를 이용하면 콘솔을 이용하지 않고 메세지를 보낼 수 있습니다.
위에 있는 function sendTopicMessage()로 시작하는 코드가  fcm api를 이용하는 nodejs코드 입니다.
원하는 시점에서 sendTopicmessage()를 호출 하시면 콘솔 없이 전송됩니다.
H**

Seungick Jang님 강제종료시에는 안되는 상태가 맞습니다 관련해서는 따로 처리를 해줘야 될듯 싶습니다.
좀 찾아보니 강제 종료시에는 프로세스를 다시 시작하는 방법으로 해야될것 같습니다.
https://www.quora.com/How-does-WhatsApp-or-Gmail-receive-notification-even-after-force-closing-them
H**

안녕하세요 ! 설 잘 보내셨는지요 ㅎㅎㅎ.. 참 많이 도움이 되고 있습니다 !
다만, 질문을 드릴게 있습니다. 작성해주신 글 덕분에 Firebase 콘솔을 이용해서 정상적으로 메시지를 보낼 수 있습니다!
그런데 혹시 node.js 서버 자체에서 바로 푸쉬를 할 수 있는 기능이 없을까요?
즉, Firebase Console 이용없이 보내고 싶습니다
박**

좋은 글 감사드립니다. 저에게 큰 도움이 되었습니다.
그리고 질문이 하나 있습니다.
알림이 foreground나 background, 슬립 상태에서는 수신이 매우 잘 됩니다.
그런데, 프로그램이 완전히 종료된 상태 (강제종료) 에서는 메시지 수신이 안되던데, 이게 특정 폰의 문제일까요? 아니면 안드로이드 자체의 문제일까요?
이 문제로 몇일째 고생중입니다. ㅠㅠ
S************

네 나머지는 위에 비어있는 img , link에 데이터 넣어서 보내시고 받는 부분은 글이랑 똑같이 만드시면 됩니다
관리자

여기까지 완전 팔로업 하기 쉽게 써주셔서 너무 감사합니다 ㅠㅠ
 JSONobject  형식으로 노티 받네요.

그럼 게시판의 (3)알림창 설정이랑 url이동 안드로이드 스튜디오에 나온것처럼 똑같이 설정하면 되는거죠 ???
a***

postman이라는 걸 처음봐서 원하시는 내용이 맞는지는 모르겠습니다
관리자

postman parameter 설정하는 법 스크린샷 추가 했습니다
관리자

답변 주셔서 너무 반갑고 또 감사합니다 ! 근데 제가 너무 아는게 없고 이쪽 분야는 처음이라서 그런지 도통 postman 쪽으로 보내는 방법만 그나마 배우게 되었고 전혀 다른 부분은 알고 있질 못하네요 ㅠ
혹시 postman으로 푸시알림 클릭시 지정한 url로 이동하는법과 이미지 올리는 방법은 없을까요..?
그것이 궁극적인 목표여서 설명대로 node.js를 통해서라도 해보려고
node.js 서버 만드는 법부터 배워보고 있었는데, 전혀 갈피를 못잡는것 같아서 여쭈어 본거였거든요 ..

일단 알려주신 방법들로 해보겠습니다!
a***

헤더 예)

con.setRequestProperty("Authorization", "key=AIzaSyZ-1u...0GBYzPu7Udno5aA");
관리자

자바에서 post로 호출하는 방법 아래 주소에 올려놓았습니다.
https://trandent.com/board/Spring/detail/754

아래 규격에 맞게 header 세팅하고 파라미터 정의해서 날리면 될걸로 보입니다

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to": "/topics/foo-bar",
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   }
}
관리자

저 방식은 node.js를 예로 들어서 설명을 한거구요 만약 jquery를 사용하신다면 $.ajax를 통해서 호출 하셔도 됩니다
지금 말씀하시는건 서버상에서 바로 호출하시는걸 말씀하시는건가요?
H**

푸시노티를 만들려고 계속 팔로업 하던 학생입니다.
fcm쪽에서 푸시를 보내는건 확인하였습니다.
그런데 nodejs 를 통한 api 호출이라고 하셔서 저 코드를 자바로 저장해서 node 파일면.js 식으로 호출하려하였는데 무반응인데

혹시 제가 잘못된길로 가고있는건가요 몇일째 헤매고 있네요 ㅠ 팁좀 부탁드립니다
a***

질문하나만 드려도 될까요? 앱을 실행중인 어플리케이션에서 종료하게 되면 (프로세스 kill)  푸시를 api통해서 보내도 받지 못하는데, 다른 상황에서는 잘 동작 합니다. 
혹시 이런 증상의 해결 방법이 있을까요? ㅠㅠ 

제가 시도해본 방법으로는 FirebaseMessagingService를 메인 액티비티에서 시작하고 FirebaseMessagingService.java 에서 onDestroy() 로 서비스를 재시작 해보려고 했으나, 해당 메소드는 안타더라구요..

작성자님께서는 프로세스가 kill된 상태에서도 동작하시나요 혹시..
S*********