마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 GCM 이용 시 백그라운드 실행 문제 질문드립니다.

0 추천

안녕하세요. 폰갭 기반으로 안드로이드 하이브리드 앱의 푸시 기능을 구현해보고 있습니다.

http://vson.tistory.com/37 (안드로이드 쪽 소스) 

http://arrkaize86.tistory.com/entry/GCM-%EC%84%9C%EB%B2%84-%EA%B5%AC%ED%98%84-%EC%98%88%EC%A0%9C3JAVA%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%ED%91%B8%EC%8B%9C-%EC%84%9C%EB%B2%84 (Java Server 쪽 소스)

이 두 링크를 보고 푸시를 구현해보았는데요, 푸시는 정상적으로 실행됩니다. 다만 앱이 실행중일때만 알림이 뜨고 앱이 꺼지거나 백그라운드에서 실행중이면 푸시가 안뜹니다. 분명 구현 초반에는 푸시를 보내면 위쪽 노티바에 떴었는데 어느 순간부터 뜨질 않네요...

 

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="msapplication-tap-highlight" content="no" />
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
    <link rel="stylesheet" type="text/css" href="css/index.css" />
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
    <script type="text/javascript">
		function tokenHandler(result){
		  console.log('deviceToken:' + result);
		}
		
		function errorHandler(err){
		  console.log('error:' + err);
		}
		function successHandler(result){
		  console.log('result:'+result);
		}
		
		function onNotificationAPN (event){
		  // 푸시 메세지에 alert 값이 있을 경우
		  if (event.alert){
		    navigator.notification.alert(event.alert);
		  }
		
		  // 푸시 메세지에 sound 값이 있을 경우
		  if (event.sound){
		    var snd = new Media(event.sound);
		    snd.play();
		  }
		
		  // 푸시 메세지에 bage 값이 있을 경우
		  if (event.badge){
		    window.plugins.pushNotification.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
		  }
		}
		
		function onNotificationGCM (e){
			switch (e.event) {
				case 'registered': // 안드로이드 디바이스의 registerID를 획득하는 event 중 registerd 일 경우 호출된다.
				{	
					console.log(e.regid);
					$('#token').val(e.regid);
					break;
				}
				case 'message': // 안드로이드 디바이스에 푸시 메세지가 오면 호출된다.
				{
					if (e.foreground){ // 푸시 메세지가 왔을 때 앱이 실행되고 있을 경우
						var soundfile = e.soundname || e.payload.sound;
						var my_media = new Media("/android_asset/www/" + soundfile);
						my_media.play();
					}
					else { // 푸시 메세지가 왔을 때 앱이 백그라운드로 실행되거나 실행되지 않을 경우
						if (e.coldstart) { // 푸시 메세지가 왔을 때 푸시를 선택하여 앱이 열렸을 경우
							console.log("알림 왔을 때 앱이 열리고 난 다음에 실행 될때");
						}
						else { // 푸시 메세지가 왔을 때 앱이 백그라운드로 사용되고 있을 경우
							console.log("앱이 백그라운드로 실행될 때");
						}
					}
					console.log(e.payload.title+"푸시받음");
					navigator.notification.alert(e.payload.msg,null,e.payload.title,'Confirm');
				}
				break;
				case 'error': // 푸시 메세지 처리에 에러가 발생하면 호출한다.
					console.log('error:' + e.msg);
					break;
				case 'default':
					console.log('알수 없는 이벤트');
					break;
			}
		}
		// 디바이스가 ready가 될때 실행될 수 있도록 이벤트 리스너에 등록한다.
		document.addEventListener("deviceready", function(){
			console.log(device.platform);
			if(device.platform.toUpperCase() == 'ANDROID'){
				window.plugins.pushNotification.register(successHandler,errorHandler, {
					"senderID" : "sender ID", // Google GCM 서비스에서 생성한 Project Number를 입력한다.
					"ecb" : "onNotificationGCM" // 디바이스로 푸시가 오면 onNotificationGCM 함수를 실행할 수 있도록 ecb(event callback)에 등록한다.
				});
			}
			else 
			{
	   	    	// PushPlugin을 설치했다면 window.plugins.pushNotification.register를 이용해서 iOS 푸시 서비스를 등록한다.
		   		window.plugins.pushNotification.register(tokenHandler, errorHandler, {
				"badge":"true", // 뱃지 기능을 사용한다.
				"sound":"true", // 사운드를 사용한다.
				"alert":"true", // alert를 사용한다.
				"ecb": "onNotificationAPN" // 디바이스로 푸시가 오면 onNotificationAPN 함수를 실행할 수 있도록 ecb(event callback)에 등록한다.
				});
	   	  	}
	   	});
	   	</script>
	   	
	    <script type="text/javascript">
	    	function insert(){
	    		var formData = $("#memForm").serialize();
	    		alert(formData);
	    		$.ajax({
	    			type:"POST",
	    			data:formData,
	    			url:"http://192.168.0.26:9102/insertMember.do",
	    			success:function(data){
	    				alert("회원가입 성공!");
	    				location.reload();
	    			},
	    			error:function(request,status,error){
	    		        alert("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error);
	    			}
	    		});
	    	}
	    	
	    	function pushTest(){
	    		$.ajax({
	    			type:"POST",
	    			url:"http://192.168.0.26:9102/pushTest.do",
	    			success:function(data){
	    				alert("푸시알림 성공?");
	    			},
	    			error:function(request,status,error){
	    		        alert("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error);
	    			}
	    		});
	    	}
	    </script>
    <title>Hello World</title>
</head>

<body>
    <div class="app">
        <h1>PhoneGap</h1>
        <form id="memForm">
			<div role="main" class="ui-content" data-inset="false">
				<input type="hidden" name="token" id="token" value="">
				<input type="text" name="id">
				<input type="password" name="pw">
				<input type="text" name="email">
				<input type="button" onclick="insert()" value="회원가입">
				<input type="button" onclick="pushTest()" value="푸시알림">
			</div>
		</form>
    </div>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="js/index.js"></script>
    <script type="text/javascript">
        app.initialize();
    </script>
</body>

</html>

 

위 소스가 안드로이드 앱 쪽 index.html 소스입니다. 처음 앱을 실행했을 때 index.html이 실행되며 해당 디바이스의 reg ID를 가져오며 그것을 회원가입 완료 버튼을 누르면 DB에 다른 정보들과 함께 저장합니다.

 

후에 Java Server에서 regID를 이용해 푸시를 날려줍니다.

 

package net.su.login.controller;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;

@Controller
public class GcmTestServer {
	@RequestMapping(value = "/pushTest.do", method = {RequestMethod.GET, RequestMethod.POST})
	@ResponseBody
	public void pushTest() throws Exception {
		try {
			// TODO Auto-generated method stub
			Sender sender = new Sender("서버 API 키"); // 서버 API Key 입력
			String regId = "regID"; // 단말기 RegID 입력
			 
			String sendTlt = "!@#$@!#$@#! 이벤트 알림";
	        String sendMsg = "오늘만 50% 파격 할인!!@!@#$#!$!";
			
	        Message message = new Message.Builder()
			.timeToLive(3) //메시지가 살아있는 시간(초단위)
			.delayWhileIdle(false) //true면 화면이 꺼진 상태일 때 수신이 안됨
			.addData("title", sendTlt)
	        .addData("msg", sendMsg)
	        .build();
			List<String> list = new ArrayList<String>();
			list.add(regId);
			MulticastResult multiResult;
		
			multiResult = sender.send(message, list, 5);
			if (multiResult != null) {
					List<Result> resultList = multiResult.getResults();
					for (Result result : resultList) {
						System.out.println(result.getMessageId());
					}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

위 소스가 Java Server 쪽 소스입니다.

실행 중이지 않을 때도 받고 싶은데 어떻게 해야하나요?

익명사용자 님이 2016년 8월 31일 질문
소스가 길어 다 읽기가 힘드네요. 일반적으로 많이 발생하는 것 중의 하나는 regID 푸쉬서버에 의해 refresh가 되었거나 삭제된 경우입니다. 리턴된 에러메세지를 잘 체크해 보세요.

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...