마스터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" />
    <script src="http://code.jquery.com/jquery-1.11.1.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가 되었거나 삭제된 경우입니다. 리턴된 에러메세지를 잘 체크해 보세요.

답변 달기

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