android GCM 클라이언트, 서버 완벽 구현 예제 4 [ 서버 셋팅, GCM 설정 ]

2016. 4. 7. 14:41mobile/android

 

 

**************************  GCM 강좌 ****************************************

 

android GCM 클라이언트, 서버 완벽 구현 1 [ 사전 준비 ]

android GCM 클라이언트, 서버 완벽 구현 2 [ 클라이언트 셋팅, GCM 설정 ]

android GCM 클라이언트, 서버 완벽 구현 3 [ 클라이언트 셋팅, GCM 설정 ]

android GCM 클라이언트, 서버 완벽 구현 4 [ 서버 셋팅, GCM 설정 ]


******************************************************************************

 

 

 

이번에는 서버를 구성해 보겠습니다.

 

GCM 서버 구축에는 web project가 필요합니다. 이 강좌에서는 jsp 와 tomcat 을 사용합니다.

java jdk, eclipse, tomcat 은 설치되어있어야 합니다.

jdk, eclipse, tomcat 설치 방법은 검색해보면 아주 많이 나와있으니 참고하시기 바랍니다.

web 지식이 부족하신 분들은 jsp hello world 출력하기 강좌를 따라하시고 오셔도 충분합니다.

 

* web project 생성 방법은 생략합니다

 

 


2016.09.26 내용추가


web project 생성에 관련한 포스팅이 추가되어서 여기에도 명시해 드립니다 ^^


Mac 에 Tomcat 설치 / 톰캣 설치 (윈도우에서의 설치는 구글링 : 클릭)

eclipse에서 tomcat 생성 / 서버생성

eclipse에서 webproject 생성 / dynamic web project / jsp



 

 

순서 요약입니다.

 

1. jar 파일 준비

2. GCMUtil.java, GCMVo.java 생성

3.  앱에서 보낸 regId 받기

4. PUSH 호출

 

 

 

 

 



 

선행작업으로 web project 를 생성합니다.

기본적인 Dynamic Web Project 여도 상관없고 spring 프레임이거나 아무거나 상관없습니다.

필자는 기본적인 Dynamic 구조로 설명하겠습니다.

 

 

1. jar 파일 준비

다음 jar 파일을 다운받습니다.

 

gcm-server.jar

 

json-simple-1.1.1.jar

 

 

그리고 WebContent > WEB-INF > lib 폴더 아래로 복사합니다.

 

 

 

 

 

 

2. GCMUtil.java, GCMVo.java 생성

 

GCMUtil.java 를 생성합니다. GCMUtil 이 하는 일은 실제 GCM PUSH 를 보내는 역할을 합니다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Message.Builder;
import com.google.android.gcm.server.MulticastResult;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
 
/**
 * GCM UTIL
 * 
 * gcm-server.jar, json-simple-1.1.1.jar 필요
 * 
 * @author 
 *
 */
public class GCMUtil {
    static final String API_KEY = "서버 API KEY"// server api key
    private static final int MAX_SEND_CNT = 999// 1회 최대 전송 가능 수
    
    // android 에서 받을 extra key (android app 과 동일해야 함)
    static final String TITLE_EXTRA_KEY = "TITLE";
    static final String MSG_EXTRA_KEY = "MSG";
    static final String TYPE_EXTRA_CODE = "TYPE_CODE";
    // android 에서 받을 extras key 
 
    List<String> resList = null;
    private Sender sender;
    private Message message;
    
    public ArrayList<GCMVo> rtnList;
 
    /**
     * GCM Util 생성자
     * RegistrationId 셋팅, sender 셋팅, message 셋팅
     * 
     * @param reslist : RegistrationId
     * @param gcmVo : msg 정보
     */
    public GCMUtil(List<String> reslist, GCMVo gcmVo) {
        sender = new Sender(API_KEY);
        this.resList = reslist;
        setMessage(gcmVo);
        rtnList = new ArrayList<GCMVo>();
        sendGCM();
    }
 
    /**
     * 메시지 셋팅
     * @param gcmVo
     */
    private void setMessage(GCMVo gcmVo) {
        Builder builder = new Message.Builder();
        builder.addData(TITLE_EXTRA_KEY, gcmVo.getTitle());
        builder.addData(MSG_EXTRA_KEY, gcmVo.getMsg());
        builder.addData(TYPE_EXTRA_CODE, gcmVo.getTypeCode());
        message = builder.build();
    }
 
    /**
     * 메시지 전송
     */
    private void sendGCM() {
        if (resList.size() > 0) {
            if (resList.size() <= MAX_SEND_CNT) { // 한번에 1000건만 보낼 수 있음
                sendMultivastResult(resList);
            } else {
                List<String> resListTemp = new ArrayList<String>();
                for (int i = 0; i < resList.size(); i++) {
                    if ((i + 1) % MAX_SEND_CNT == 0) {
                        sendMultivastResult(resListTemp);
                        resListTemp.clear();
                    }
                    resListTemp.add(resList.get(i));
                }
 
                // 1000건씩 보내고 남은 것 보내기
                if(resListTemp.size() != 0){
                        sendMultivastResult(resListTemp);
                }
            }
        }
 
    }
 
    /**
     * 실제 멀티 메시지 전송
     * 
     * @param list
     */
    private void sendMultivastResult(List<String> list) {
        try {
            
            MulticastResult multiResult = sender.send(message, list, 5); // 발송할 메시지, 발송할 타깃(RegistrationId), Retry 횟수
            List<Result> resultList = multiResult.getResults();
            
            
            for (int i=0; i<resultList.size(); i++){
                Result result = resultList.get(i);
 
                // 결과 셋팅
                GCMVo rtnGcmVo = new GCMVo();
                rtnGcmVo.setRegId(list.get(i));
                rtnGcmVo.setMsgId(result.getMessageId());
                rtnGcmVo.setErrorMsg(result.getErrorCodeName());
            
                if (result.getMessageId() != null) { // 전송 성공
                    rtnGcmVo.setPushSuccessOrFailure(true);
                } else { // 전송 실패
                    rtnGcmVo.setPushSuccessOrFailure(false);
                }
                
                rtnList.add(rtnGcmVo);
            }
 
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
 
cs

20# : 메모한 서버 API-KEY 를 넣습니다.

24# ~ 26# : 3번 강좌에 설명해 놓았습니다. android project의 GCMIntentService.java 클래스에 19# ~ 21# 과 동일해야 합니다.

67# : 메시지를 한번에 보낼수 있는 최대 갯수는 1000개입니다. 안전성을 위해 999개씩 보내도록 분기합니다.

 

 

GCMVo.java 생성합니다. GCMVo 는 PUSH를 보낼 때 정보를 담는 역할을 합니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
 
public class GCMVo {
    // android 로 보낼 정보
    private String title = "제목입니다.";
    private String msg = "내용입니다.";
    private String typeCode = "코드입니다.";
    
    // push 결과 정보
    private String regId; // regId
    private boolean pushSuccessOrFailure; // 성공 여부
    private String msgId = ""// 메시지 ID
    private String errorMsg = ""// 에러메시지
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) throws UnsupportedEncodingException {
        this.title = URLEncoder.encode(title, "UTF-8");
    }
 
    public String getMsg() {
        return msg;
    }
 
    public void setMsg(String msg) throws UnsupportedEncodingException {
        this.msg = URLEncoder.encode(msg, "UTF-8");
    }
 
    public String getTypeCode() {
        return typeCode;
    }
 
    public void setTypeCode(String typeCode) {
        this.typeCode = typeCode;
    }
 
    public boolean getPushSuccessOrFailure() {
        return pushSuccessOrFailure;
    }
 
    public void setPushSuccessOrFailure(boolean pushSuccessOrFailure) {
        this.pushSuccessOrFailure = pushSuccessOrFailure;
    }
 
    public String getErrorMsg() {
        return errorMsg;
    }
 
    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
 
    public void setRegId(String regId) {
        this.regId = regId;
    }
 
    public String getMsgId() {
        return msgId;
    }
 
    public void setMsgId(String msgId) {
        this.msgId = msgId;
    }
 
    public String getRegId() {
        return regId;
    }
    
    
    
}
 
cs

 

 

 

 

 

 

3.  앱에서 보낸 regId 받기

 

PUSH를 보내려면 디바이스의 regId 가 있어야 합니다.

android project 에서 로그로 regId 를 출력하고 있어서 복사해서 호출할 때 그냥 사용해도 무방합니다.

하지만 앱실행 > 앱에서 서버로 regId 전송 > 서버에서 regId 수집 및 저장 > 수집된 regId로 PUSH 호출 > 앱에서 PUSH 수신 과 같은 로직이 있어야 사용하기 편하기 때문에 받는 부분을 꼭 구현하시기 바랍니다.

 

 

 

WebContent 폴더 아래에 sendGCMReg.jsp 파일을 생성합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@page import="java.net.URLEncoder"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@ page language="java" contentType="text/json; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%
 
    System.out.println("*********************************************************");
    System.out.println("REG 획득");
    System.out.println("KEY : " + request.getParameter("KEY"));
    System.out.println("REG : " + request.getParameter("REG"));
    System.out.println("*********************************************************");
    
    Map rtnMap = new HashMap();
    
    rtnMap.put("DATA", URLEncoder.encode("등록되었습니다.""UTF-8"));
    rtnMap.put("DATA1""END1");
    out.print(rtnMap.toString());
 
%>
cs

 

 

그리고 sendGCMReg.jsp 를 호출하는 주소를 andorid project 의 MainActivity.java 의 SERVER_URL 변수에 셋팅합니다.

대략 http://111.111.111.111:8080/sendGCMReg.jsp 이런 모양이 되겠네요.

 

이제 앱을 실행합니다. 에뮬레이터 말고 인터넷이 가능한 스마트폰에서 꼭 실행하도록 합니다.

여기서 실행하면 더이상 앱에서는 오류가 발생하지 않습니다.

 

 

버튼을 클릭해 봅니다.

 

그럼 서버의 eclipse 의 console 에 REG 정보가 찍혀있을 것입니다.

 

여기서 획득한 regId 정보를 메모합니다.

 

regId 정보를 db에 넣어서 관리할 수 도 있겠죠 ???

 

 

 



 

4. PUSH 호출

 

regId 도 획득했으니 이제 regId 를 이용하여 PUSH 를 직접 보내봅시다.

 

WebContent 폴더 아래에 sendGCM.jsp 파일을 생성합니다.

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
32
33
<%@page import="esaving.module.common.pushmobile.GCMUtil"%>
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@page import="esaving.module.common.pushmobile.GCMVo"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%
 
    //전달할 PUSH 내용
    String title = "PUSH 제목 입니다.";
    String msg = "PUSH 내용입니다 ^^ !!!!";
    
    // GCM 정보 셋팅
    GCMVo gcmVo = new GCMVo();
    gcmVo.setTitle(title);
    gcmVo.setMsg(msg);
    gcmVo.setTypeCode("");
    
    // GCM reg id 셋팅
    List<String> reslist = new ArrayList<String>();
    reslist.add("입력받은 regId를 입력합니다.");
    
    GCMUtil gcmUtil = new GCMUtil(reslist, gcmVo);
    
   for(int i=0; i<gcmUtil.rtnList.size(); i++){
      GCMVo rtnGcmVo = gcmUtil.rtnList.get(i); 
 
      out.println("regId : " + rtnGcmVo.getRegId());
      out.println("성공 여부 : " + rtnGcmVo.getPushSuccessOrFailure());
      out.println("메시지ID : " + rtnGcmVo.getMsgId());
      out.println("에러메시지 : " + rtnGcmVo.getErrorMsg());
   } 
 %>
cs

10# ~ 17# : PUSH 보낼 내용을 셋팅합니다.

21# : 입력받은 regId 를 입력합니다.

30# : 에러메시지가 NotRegistered 이면 앱이 삭제됬다고 판단하면 된다. 비교할 수 있는 상수는 Constants.ERROR_NOT_REGISTERED 입니다.

실제로 앱이 삭제되고 google gcm 서버로 regId 가 삭제하는 메시지를 보내고 적용되는 시간이 조금 걸리니 앱 삭제 후 바로 테스트하는 것은 의미없습니다.

 

 

sendGCM.jsp 를 호출 해 주면 PUSH 가 도착하는 것을 볼 수 있습니다.

 

대략 http://111.111.111.111:8080/sendGCM.jsp 과 같은 주소이겠죠 ?

 

 

 

이상으로 GCM 클라이언트(어플리케이션)와 서버를 완벽하게 구현하는 강좌를 마칩니다.