안녕하세요. 폰갭 기반으로 안드로이드 하이브리드 앱의 푸시 기능을 구현해보고 있습니다.
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 쪽 소스입니다.
실행 중이지 않을 때도 받고 싶은데 어떻게 해야하나요?