차근차근/Android

Google Cloud Messaging / GCM

예쁜꽃이피었으면 2014. 7. 29. 00:54
http://blog.naver.com/action713/220015435931

http://leminity.tistory.com/26

http://leminity.tistory.com/27

http://leminity.tistory.com/28

 

잘 정리되어 있다.   열심히 봐둬야지

 

Google Cloud Messaging for Android(1/3)


Google Cloud Messging이란 Google에서 제공하는 메시지 발송 서비스로서

자신이 개발한 어플리케이션을 사용하는 사용자들에게 메시지를 발송할 수 있는

구글에서 제공하는 서비스 시스템이다.

 

본 주제는 크게 3개로 나뉘어 포스팅 되며, 포스팅 순서는 다음과 같다.

 

1.Google Cloud Messaging for Android 개요

2.구현 - GCM 적용 Sample Application 구현

3.구현 - Sample Application에 메시지 발송을 위한 Sample 구현


그럼 이제부터 GCM이란 무엇인지 먼저 알아보도록 하자.

 

 

 

1. GCM이란?

Google Cloud Messaging(이하 GCM으로 통칭)은 Google 서버를 이용(이하 GCM Server로 통칭)하여

사용자 개개인의 디바이스 내 어플리케이션 단위로 타겟팅을 하여 메시지를 전송할 수 있는 Service이다.

해당 서비스를 이용하기 위해선 최소 Android 2.2 Froyo(apiLevel 8)가 되어야 한다.


2. GCM 발송

개발자는 GCM Server를 통해 최대 4Kb 크기의 메시지를 전송 가능하며, 이를 통해 개발자는 GCM을 적용한 자신의 어플리케이션을 사용한 사용자에게 자신이 원하는 액션을 사용자에게 제공할 수 있다.

(예 : 공지사항, 어플리케이션 홍보)

 

3. GCM Process

GCM을 이용하기 위해선 Google의 GCM 홈페이지(http://developer.android.com/google/gcm/index.html)

에서 apiKey, Project ID 2개의 값을 발급받아야 한다.

 

GCM 발송프로세스은 하단의 그림을 참조하도록 한다.

 

<그림. GCM 발송 프로세스>  


*전제 조건

Google에서 제공하는 라이브러리를 통해 GCM으로부터 ID발급 요청 및 메시지를 수신하기 위한 GCMIntentService

(Android Service Component)가 적용되어 있어야 함.

 

GCM 발송 프로세스

1)어플리케이션에서 Registration Id를 발급 요청한다.

   (디바이스의 어플리케이션 단위로 타겟팅 되므로 GCM 서버에 PROJECT ID를 서버에 전송)

2)발급된 ID를 리턴 받는다.

3)어플리케이션은 발급된 ID를 발송자(Message Sender)에게 전달한다.

4)발송자는 전달받은 Registration ID를 저장한다.

   (메시지를 발송할 때 Regsitration ID로 발송할 타겟을 지정하기 위해 registration Id가 필요하다.)

5)저장한 Registration ID와 GCM에서 발급받은 apiKey를 통해 사용자의 어플리케이션에 메시지 발송을 요청한다.

6)GCM Server는 apiKey와 Registration ID를 통해 발송받을 어플리케이션을 타겟팅하여 메시지를 전송한다.7)메시지 전송 결과를 발송자에게 리턴한다.

   (정상 발송, 사용자가 어플리케이션을 삭제하여 전송할 수 없는 경우, 네트워크 오류 등에 대한 결과를

    리턴하게 된다.)


4.GCM 서비스 이용 방법(그림 교체 필요)

 상기 3.GCM Process에 언급되었던 apiKey와 registration ID를 발급받는 절차를 설명한다.

 http://developer.android.com/google/gcm/index.html에서 apiKey와 Project ID를 발급 받을 수 있다.

1) http://developer.android.com/google/gcm/index.html에서 Getting Started 선택

 

2) Google APIs Console Page 선택


3) Create Project... 선택 후 프로젝트 생성(자신이 원하는 프로젝트 명을 입력한다.)


 

4) 화면의 왼쪽 상단에서 Services 메뉴를 선택



 

 

5) Google Cloud Messaging for Android를 ON으로 선택


 

 

6) 화면 오른쪽 상단 메뉴에서 Overview 선택 후 Project Number(Project ID)를 확인(어플리케이션에 해당 키를 적용해야 한다.)



 


7) 화면 오른쪽 상단 메뉴에서 API Access 선택 후 API Key 확인 가능(어플리케이션으로 메시지를 발송할 때 필요)



 

 

 

 

 

 

구현

실제 구현에 대해서는 2편에서 다루기로 하겠다.

Google Cloud Messaging for Android

앞서 Google Cloud Messaging이 무엇인지에 대해 알아보았다.
이제부터는 실제 구현한 샘플 소스를 통해 어떻게 사용할 수 있는지 알아보도록 한다.


GCM 메시지 발송을 하기 위해선 Registration Id를 필요로 하므로 GCM 적용을 통해

RegistrationId 발급 및 메시지 처리를 구현한 어플리케이션에 소스를 첨부하니 참고 바란다.

구현 순서는 다음과 같다.


1.어플리케이션 프로젝트 내 GCM ID 발급 요청 프로세스 
2.GCM Cloud Message를 처리하기 위해 GCMBaseIntentService를 상속한 GCMIntentService의 구현


 1. MainActivity.java - 어플리케이션 내 GCM ID 발급 요청 프로세스
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
package com.leminity.gcmsampleapp;
 
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
 
import com.google.android.gcm.GCMRegistrar;
 
/**
 * GCM Service 이용을 위한 샘플 프로젝트
 * @author Leminity
 *
 */
public class MainActivity extends Activity {
     
    private static final String TAG ="MainActivity";
    private static final String PROJECT_ID=""; //Google Cloud Messageing Service PROJECT ID
    private Context appContext = null;//applicationContext
     
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         
        initialize();//변수 초기화
        startGCM();//GCM 시작 메소드
    }
     
    private void initialize(){
        appContext = getApplicationContext();
    }
     
    /**
     * GCM 서비스를 시작한다.
     */
    private void startGCM(){
         
        /**
         * GCM Service가 이용 가능한 Device인지 체크한다.
         * api 8(Android 2.2) 미만인 경우나 GCMService를 이용할 수 없는
         * 디바이스의 경우 오류를 발생시키니 반드시 예외처리하도록 한다.
         */
        try {
            GCMRegistrar.checkDevice(appContext);
        } catch (Exception e) {
            // TODO: handle exception
            Log.e(TAG, "This device can't use GCM");
            return;
        }
         
         
        /**
         * 2.SharedPreference에 저장된 RegistrationID가 있는지 확인한다.
         * 없는 경우 null이 아닌 ""이 리턴
         */
        String regId = GCMRegistrar.getRegistrationId(appContext);
         
        /**
         * Registration Id가 없는 경우(어플리케이션 최초 설치로 발급받은 적이 없거나,
         * 삭제 후 재설치 등 SharedPreference에 저장된 Registration Id가 없는 경우가 이에 해당한다.)
         */
        if(CommonUtils.isEmpty(regId)){
            /**
             * 3.RegstrationId가 없는 경우 GCM Server로 Regsitration ID를 발급 요청한다.
             * 발급 요청이 정상적으로 이루어진 경우 Registration ID는 SharedPreference에 저장되며,
             * GCMIntentService.class의 onRegistered를 콜백한다.
             */
            GCMRegistrar.register(appContext, PROJECT_ID);
             
        //SharedPreference에 저장된 Registration Id가 존재하는 경
        }else{
            Toast.makeText(appContext, "Exist Registration Id: " + regId, Toast.LENGTH_LONG).show();
        }
    }
 
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        /**
         * 4.앱 종료되기 전이나 종료하기 전에 GCMRegistrar.onDestroy를 반드시 호출한다.
         * 호출하지 않을 경우 unRegisterReceiver오류가 발생한다.
         * 해당 함수는 null이나 기타 오류에 대해 내부적으로 예외 처리하고 있으므로, 아무때나 마음껏 호출해도 된다.
         */
        GCMRegistrar.onDestroy(appContext);
        super.onDestroy();
    }
 
}
2.GCM을 통해 수신한 Registration ID 및 Message 처리를 위한 소스이다.
 GCMIntentService.class는 반드시 GCMIntentService라는 이름으로 생성되어야 하며,
 어플리케이션 루트 패키지에 위치해야 한다. 상세한 내용은 소스 내 주석을 확인한다.
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
<p>package com.leminity.gcmsampleapp;
 
import android.content.Context;
import android.content.Intent;
 
import com.google.android.gcm.GCMBaseIntentService;
 
/**
 * GCMBaseIntentService를 상속받은 클래스를 프로젝트 루트 패키지에 생성한다.
 * 클래스는 반드시 다음 조건을 충족해야 한다.
 *
 * 1.클래스명은 GCMIntentService여야 한다.
 * 2.반드시 루트 패키지 내에 선언되어 있어아 한다.
 *  상기 1,2 조건을 만족해야 하는 이유는 라이브러리 내에서 GCMService를 시작하는 부분이
 *  'GCMIntentService'라는 명칭으로 하드코딩되어 적용되어 있다.
 * @author Leminity
 *
 */
public class GCMIntentService extends GCMBaseIntentService {
 
    /**
     * GCM Server로부터 발급받은 Project ID를 통해 SuperClass인
     * GCMBaseIntentService를 생성해야한다.
     */
    public GCMIntentService() {
        super(Constants.PROJECT_ID);
        // TODO Auto-generated constructor stub
    }
 
    @Override
    protected void onError(Context arg0, String arg1) {
        // TODO Auto-generated method stub
        /**
         * GCM 오류 발생 시 처리해야 할 코드를 작성한다.
         * ErrorCode에 대해선 GCM 홈페이지와 GCMConstants 내 static variable 참조한다.
         */
         
 
    }
 
    @Override
    protected void onMessage(Context arg0, Intent arg1) {
        // TODO Auto-generated method stub
        /**
         * GCMServer가 전송하는 메시지가 정상 처리 된 경우 구현하는 메소드이다.
         * Notification, 앱 실행 등등 개발자가 하고 싶은 로직을 해당 메소드에서 구현한다.
         * 전달받은 메시지는 Intent.getExtras().getString(key)를 통해 가져올 수 있다.
         */
 
    }
 
    @Override
    protected void onRegistered(Context arg0, String regId) {
        // TODO Auto-generated method stub
        /**
         * GCMRegistrar.getRegistrationId(context)가 실행되어 registrationId를 발급받은 경우 해당 메소드가 콜백된다.
         * 메시지 발송을 위해 regId를 서버로 전송하도록 하자.
         */
 
    }
 
    @Override
    protected void onUnregistered(Context arg0, String arg1) {
        // TODO Auto-generated method stub
        /**
         * GCMRegistrar.unregister(context) 호출로 해당 디바이스의 registrationId를 해지요청한 경우 해당 메소드가 콜백된다.
         */
 
    }
 
}
</p>

3. 공통 함수를 모아놓은 공통 유틸 클래스이다.

 구현하기 귀찮으면 상기 소스에서 직접 하단의 내용을 적용해도 무방하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.leminity.gcmsampleapp;
 
public class CommonUtils {
     
     
    /**
     * 인자값이 null이거나 trim의 결과가 ""인 경우 true를 리턴한다.
     * @param String
     * @return boolean
     */
    public static boolean isEmpty(String value){
         
        boolean isEmpty = false;
         
        if((value == null) || value == null)
            isEmpty = true;
         
        return isEmpty;
    }
 
}

4.상수 전용 클래스이다. 구현하기 귀찮으면 소스 내 상수를 적용해도 무방하다.

1
2
3
4
5
6
7
package com.leminity.gcmsampleapp;
 
public class Constants {
     
    public static final String PROJECT_ID="";//GCM으로부터 발급받은 PROJECT_ID
 
}
5.AndroidManifest.XML에 Receiver와 Service 및 Permission을 추가해야 한다.
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
<!--?xml version="1.0" encoding="utf-8"?-->
<manifest android:versionname="1.0" android:versioncode="1" package="com.leminity.gcmsampleapp" xmlns:android="http://schemas.android.com/apk/res/android">
 
    <uses-sdk android:targetsdkversion="17" android:minsdkversion="8">
 
    <application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:allowbackup="true">
        <activity android:label="@string/app_name" android:name="com.leminity.gcmsampleapp.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN">
 
                <category android:name="android.intent.category.LAUNCHER">
            </category></action></intent-filter>
        </activity>
     
    <!-- GCMReceiver 추가 -->
    <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE">
        <action android:name="com.google.android.c2dm.intent.REGISTRATION">
        <category android:name="my_app_package">
      </category></action></action></intent-filter>
    </receiver>
    <!-- GCMIntentService 추가 -->
    <service android:name=".GCMIntentService">
    </service></application>
     
    <!-- GCM Permission 추가 -->
    <permission android:name="com.leminity.gcmsampleapp.permission.C2D_MESSAGE" android:protectionlevel="signature">
    <uses-permission android:name="com.leminity.gcmsampleapp.permission.C2D_MESSAGE">
    <!-- GCM User Permission 추가 -->
    <!-- App receives GCM messages. -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE">
    <!-- GCM connects to Google Services. -->
    <uses-permission android:name="android.permission.INTERNET">
    <!-- GCM requires a Google account. -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS">
    <!-- Keeps the processor from sleeping when a message is received. -->
    <uses-permission android:name="android.permission.WAKE_LOCK">
</uses-permission></uses-permission></uses-permission></uses-permission></uses-permission></permission></uses-sdk></manifest>

 

상기 내용을 구현한 샘플용 프로젝트를 첨부하니 참고가 되었으면 한다.


 

 GCMSampleApp.zip

Google Cloud Messging For Android(3/3)

 

거의 다 왔다. 정말이다.

하단에 추가된 GCM을 이용한 메시지 발송 샘플을 구현하면 실제 메시지를 발송할 수 있으며,

이를 커스터마이즈하여 실제 프로젝트에서도 사용가능하다.


 

1.GCM을 이용한 Message 발송하기

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
<p>import java.net.URLEncoder;
 
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
 
/**
 * GCM 메시지 발송을 위한 샘플 구현 소스이다.
 * 하단의 내용을 커스터마이즈하여 실제 서버단에서 발송모듈로 구현 가능하다.
 * @author Leminity
 *
 */
public class GCMTest {
     
    private static final String REGISTRATION_ID = "";//registration Id 입력
    private static final String APIKEY = ""; //GCM에서 발급받은 ApiKey를 입력
     
    public static void main(String[] args) {
        try {
            String sendTlt = "타이틀 제목";
            String sendMsg = "내용 : 메시지가 보입니다";
  
            Sender sender = new Sender(APIKEY);
             
            /**
             * message Build 부분에서 addData로 추가한 값은 어플리케이션의
             * onMessage(context, intent)에서 Intent로 전달되며
             * intent.getExtras().getString("title")형태로 얻어와 사용 가능하다.
             */
            Message message = new Message.Builder()
            .addData("title", URLEncoder.encode(sendTlt, "UTF-8"))
            .addData("msg", URLEncoder.encode(sendMsg, "UTF-8"))
            .build();
  
            //발송할 메시지, 발송할 타깃(RegistrationId, Retry 횟수)
            Result result = sender.send(message, REGISTRATION_ID, 3);
            if (result.getMessageId() != null) {
                System.out.println("Send success");
            } else {
                String error = result.getErrorCodeName();
                System.out.println("Send fail : " + error);
            }
  
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
}</p>

 

 

상기 소스에서 상수로 잡혀 있는 registration Id는 디바이스 내 어플리케이션에서 GCM에 등록을 요청하여

발급받는 값이며 ApiKey는 GCM에 프로젝트 생성으로 발급받은 값을 의미한다.

이해가 가지 않는다면 1, 2편 포스팅을 다시 참고하기 바란다.


 



반응형