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

 

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

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

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

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


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

 

 

이번에는 클라이언트를 셋팅해 보겠습니다.

 

앞에서 만든 android 프로젝트에 GCM 설정을 하겠습니다.

 

 

 

android 프로젝트에서 할 일은 다음과 같습니다.

GCM 을 수신할 reg Id 를 저장하기 및 서버로 보내기

GCM 메시지 수신하기

수신한 GCM 메시지를 상태바에 띄우기

 

이 간단한 3가지 작업을 하기 위해서는 많은 스킬이 필요하니 집중해서 따라오시기 바랍니다.

 

 

 

순서 요약입니다.

 

1. main.xml 셋팅

2. build.gradle (Module:app) 셋팅

3. MainActivity.java 셋팅

4. HttpUtil.java 생성

 

 



 

1. main.xml 셋팅

1
2
3
4
5
6
7
8
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="RegistrationId 를 서버로 전송"
        android:id="@+id/button"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
cs

단순하게 버튼 하나 설정하고 넘어가겠습니다.

위 버튼의 역할은 서버로 regId 를 전송하는 이벤트로 사용됩니다.

 

RegistrationId 를 regId 로 모든 강좌에 줄여서 설명하겠습니다.

RegistrationId 는 단말기를 GCM 서버에 등록 후 받아오는 고유한 KEY 값이라 생각하면 됩니다. 이 값은 어플리케이션을 설치 또는 업데이트 등의 작업이 일어나고 다시 등록을 하게되면 변경되니 최신의 값을 유지해야 합니다.

 

 

 

2. build.gradle (Module:app) 셋팅

 

라이브러리를 등록한다고 생각하시면 됩니다.

 

1
2
compile "com.google.android.gms:play-services-gcm:8.4.0"
compile (group: 'org.apache.httpcomponents' , name: 'httpmime' , version: '4.3.5') { exclude module: 'org.apache.httpcomponents:httpclient'}
cs

 

위 두 라인을 build.gradle (Module:app) 의 dependencies{ } 안에 셋팅합니다.

1# : gcm을 사용하려면 play-services-gcm 이 필요합니다.

2# : http 통신을 하기 위해서는 httpcomponents 가 필요합니다.

 

 

위와 같은 모양으로 셋팅하면 됩니다.

 

 

 

 

 

3. MainActivity.java 셋팅

 

설명은 주석으로 대체합니다.

HttpUtil 클래스는 애러가 나는게 당연합니다. 일단 무시하고 지나갑니다.

 

 

 

import 정보 (참고용)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.Toast;
cs

변수 선언부

1
2
3
4
5
6
7
8
9
10
11
12
    // SharedPreferences에 저장할 때 key 값으로 사용됨
    public static final String PROPERTY_REG_ID = "registration_id";
 
    // SharedPreferences에 저장할 때 key 값으로 사용됨
    public static final String PROPERTY_APP_VERSION = "appVersion";
 
    static String SENDER_ID = "11111111111"// 프로젝트 번호
    static String SERVER_URL = "http://111.111.111.111:8080/gcm/sendGCMReg.do"// 서버 주소
    GoogleCloudMessaging gcm;
    Context context;
    String regid;
    private Button btn;
cs

7# : 메모한 프로젝트 번호를 입력합니다.

8# : 서버 url을 입력합니다. 아직 없으니 비워두셔도 상관없습니다.

 

 

 

onCreate 내부 삽입 소스 ( onCreate 함수 내부 하단에 복사해서 붙혀넣기 합니다. )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        context = this;
 
        btn = (Button) findViewById(R.id.button);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                HttpUtil hu = new HttpUtil(context);
                String[] params = {SERVER_URL, "KEY:1234""REG:" + regid};
                hu.execute(params);
            }
        });
 
        // gcm 등록
        gcm = GoogleCloudMessaging.getInstance(this); // GoogleCloudMessaging 클래스의 인스턴스를 생성한다
        regid = getRegistrationId(context); // 기존에 발급받은 등록 아이디를 가져온다
 
        if (regid.isEmpty()) { // 기존에 발급된 등록 아이디가 없으면 registerInBackground 메서드를 호출해 GCM 서버에 발급을 요청한다.
            System.out.println("************************************************* gcm 발급");
            registerInBackground();
        }
 
        System.out.println("************************************************* gcm regid : " + regid);
cs

 

 

 

메소드 ( MainActivity 클래스 내부에 복사에서 붙혀넣기 합니다. )

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
    // 저장된 reg id 조회
    private String getRegistrationId(Context context) {
        final SharedPreferences prefs = getGCMPreferences(context); // 이전에 저장해둔 등록 아이디를 SharedPreferences에서 가져온다.
        String registrationId = prefs.getString(PROPERTY_REG_ID, ""); // 저장해둔 등록 아이디가 없으면 빈 문자열을 반환한다.
        if (registrationId.isEmpty()) {
            System.out.println("************************************************* Registration not found.");
            return "";
        }
 
        // 앱이 업데이트 되었는지 확인하고, 업데이트 되었다면 기존 등록 아이디를 제거한다.
        // 새로운 버전에서도 기존 등록 아이디가 정상적으로 동작하는지를 보장할 수 없기 때문이다.
        int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
        int currentVersion = getAppVersion(context);
        if (registeredVersion != currentVersion) { // 이전에 등록 아이디를 저장한 앱의 버전과 현재 버전을 비교해 버전이 변경되었으면 빈 문자열을 반환한다.
            System.out.println("************************************************* App version changed.");
            return "";
        }
        return registrationId;
    }
 
    private SharedPreferences getGCMPreferences(Context context) {
        return getSharedPreferences(MainActivity.class.getSimpleName(),
                Context.MODE_PRIVATE);
    }
 
    private static int getAppVersion(Context context) {
        try {
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            // should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
    }
 
    // reg id 발급
    private void registerInBackground() {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                String msg = "";
                try {
                    if (gcm == null) {
                        gcm = GoogleCloudMessaging.getInstance(context);
                    }
                    regid = gcm.register(SENDER_ID);
                    msg = "Device registered, registration ID=" + regid;
 
                    // 서버에 발급받은 등록 아이디를 전송한다.
                    // 등록 아이디는 서버에서 앱에 푸쉬 메시지를 전송할 때 사용된다.
                    sendRegistrationIdToBackend();
 
                    // 등록 아이디를 저장해 등록 아이디를 매번 받지 않도록 한다.
                    storeRegistrationId(context, regid);
                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();
                    // If there is an error, don't just keep trying to register.
                    // Require the user to click a button again, or perform
                    // exponential back-off.
                }
                return msg;
            }
 
            @Override
            protected void onPostExecute(String msg) {
                System.out.println("****************************************************************************** msg : " + msg);
            }
 
        }.execute(nullnullnull);
    }
 
    // SharedPreferences에 발급받은 등록 아이디를 저장해 등록 아이디를 여러 번 받지 않도록 하는 데 사용
    private void storeRegistrationId(Context context, String regid) {
        final SharedPreferences prefs = getGCMPreferences(context);
        int appVersion = getAppVersion(context);
        System.out.println("************************************************* Saving regId on app version " + appVersion);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(PROPERTY_REG_ID, regid);
        editor.putInt(PROPERTY_APP_VERSION, appVersion);
        editor.commit();
    }
 
    // 등록 아이디를 서버(앱이랑 통신하는 서버)에 전달
    // 서버는 이 등록 아이디를 사용자마다 따로 저장해두었다가 특정 사용자에게 푸쉬 메시지를 전송할 때 사용할 수 도 있음
    private void sendRegistrationIdToBackend() {
        System.out.println("************************************************* 서버에 regid 전달 : " + regid);
 
        HttpUtil hu = new HttpUtil(context);
        String[] params = {SERVER_URL, "KEY:1234""REG:" + regid};
        hu.execute(params);
    }
 
    // 토스트 생성 함수
    public void printToast(String txt) {
        Toast.makeText(this, txt, Toast.LENGTH_SHORT).show();
    }
 
cs

 

 

 



 

 

4. HttpUtil.java 생성

HttpUtil 은 서버와 통신할 클래스입니다. 발급된 regid를 서버로 전송하고 그 결과값을 받아옵니다.

 

HttpUtil.java 파일을 하나 만드세요

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
import android.content.Context;
import android.os.AsyncTask;
 
import org.json.JSONException;
import org.json.JSONObject;
 
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
 
/**
 * Created by on 2016-04-05.
 */
public class HttpUtil extends AsyncTask<StringStringString> {
    private Context context;
 
    public HttpUtil(Context context) {
        this.context = context;
    }
 
    @Override
    protected void onPreExecute() {
        // 호출 전
        System.out.println("************************************************* 서버 호출 선행" );
    }
 
 
    @Override
    public String doInBackground(String... params) {
        System.out.println("************************************************* 서버 호출" );
        String paramString = "";
        String url = params[0];
        String param1Key = params[1].split(":")[0];
        String param1Value = params[1].split(":")[1];
        String param2Key = params[2].split(":")[0];
        String param2Value = params[2].split(":")[1];
        System.out.println("************************************************* 서버 호출 url : " + url);
 
        paramString = param1Key  + "=" + param1Value + "&" + param2Key  + "=" + param2Value ;
 
        try {
            URL obj = new URL(url + "?" + paramString);
            HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
 
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-Type""application/json");
 
            byte[] outputInBytes = params[0].getBytes("UTF-8");
            OutputStream os = conn.getOutputStream();
            os.write( outputInBytes );
            os.close();
 
            int retCode = conn.getResponseCode();
 
            System.out.println("************************************************* 서버 호출 결과 코드 : " + retCode );
            if (retCode == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                char[] buff = new char[512];
                int len = -1;
                String line;
                StringBuffer response = new StringBuffer();
                while((len = br.read(buff)) != -1) {
                    response.append(new String(buff, 0, len));
                }
                br.close();
                System.out.println("************************************************* 서버 호출 결과 text : " + response.toString());
 
                return response.toString();
            }else{
                System.out.println("************************************************* 서버 호출 실패 code : " + retCode );
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    // 호출이 끝난 후
    @Override
    protected void onPostExecute(String result) {
        JSONObject object = null;
        try {
            object = new JSONObject(result);
        } catch (JSONException e) {
            e.printStackTrace();
        }
 
        System.out.println("************************************************* 서버 호출 후행");
        String rtn = "";
        try {
            // return 받은 Json 데이터
            rtn = URLDecoder.decode(object.getString("DATA"), "UTF-8");
            ((MainActivity) context).printToast(rtn);
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
 
 
    }
 
}
 
cs

 

 

 

 

 

지금까지 어플에서의 GCM 설정 및 regId를 서버로의 전송할 준비를 마쳤습니다.

 

다음 강좌에서는 서버에서 보내는 PUSH 를 받는 부분과 AndroidManifest.xml 설정 대해 설명합니다.

 

 

by 개발자 CofS 2016.04.07 11:10
  • sun 2016.11.14 19:34 신고 ADDR EDIT/DEL REPLY

    안녕하세요. 뭐 좀 여쭤볼께요!
    저기 2번 작업에서 이클립스 android sdk 사용시에는 어떤 작업을 해야 될지 잘 모르겠습니다 ㅠㅠ
    2. build.gradle (Module:app) 셋팅 이 작업입니다.

    • Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS 2016.11.15 09:07 신고 EDIT/DEL

      gradle 파일에 사용하실 라이브러리를 등록해주시면 됩니다 ^^

  • 흐접 2016.12.06 10:34 신고 ADDR EDIT/DEL REPLY

    MainActivity에 등록하는 프로젝트 ID라는게 프로젝트 번호 숫자 12자리인가요?? 아니면 프로젝트ID를 입력하는 건가요?

    • Favicon of https://cofs.tistory.com BlogIcon 개발자 CofS 2016.12.06 13:13 신고 EDIT/DEL

      프로젝트 번호가 맞습니다 ^^
      좋은 지적감사합니다.
      본문에 혼돈이 없도록 수정해놓았습니다. ^^

    • 흐접 2016.12.06 13:53 신고 EDIT/DEL

      아 네! 그리고 예제3번에 질문을 했는데 답변 부탁드립니다.ㅠㅠ