출처: http://cofs.tistory.com/177?category=627173
************************** 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(null, null, null);
}
// 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<String, String, String> {
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 설정 대해 설명합니다.
'mobile > android' 카테고리의 다른 글
android 현재 WebView에서 외부 페이지 불러오기 / WebView 새창 띄우지 않기 / WebViewClient (0) | 2016.04.20 |
---|---|
android webview 에서 카메라 호출 및 사진첩(갤러리) 호출하여 이미지 파일 업로드 하기 (21) | 2016.04.14 |
android html5 스마트폰 카메라와 연결하기, 사진(갤러리) 및 동영상 찍기 예제 ( URL.createObjectURL ) (0) | 2016.04.08 |
android GCM 클라이언트, 서버 완벽 구현 예제 4 [ 서버 셋팅, GCM 설정 ] (121) | 2016.04.07 |
android GCM 클라이언트, 서버 완벽 구현 예제 3 [ 클라이언트 셋팅, GCM 설정 ] (5) | 2016.04.07 |
android GCM 클라이언트, 서버 완벽 구현 예제 2 [ 클라이언트 셋팅, GCM 설정 ] (5) | 2016.04.07 |
android GCM 클라이언트, 서버 완벽 구현 예제 1 [ 사전 준비 ] (1) | 2016.04.07 |
Android OCR 한글 및 영문 인식 Tesseract 샘플 프로젝트 테스트 (110) | 2016.04.06 |
android | 꺼진 화면에서 앱 실행하기 / 잠든 화면 깨우기 / 잠금 화면 위로 실행/ (6) | 2016.03.30 |
android | 디바이스 부팅시 앱 실행하는 방법 / 재부팅 시 어플 실행하는 방법 (0) | 2016.03.30 |
android webview url 가로채기 / 네이티브에서 작업 | android (0) | 2016.01.05 |
'개발 > APP' 카테고리의 다른 글
android GCM 클라이언트, 서버 완벽 구현 4 [ 서버 셋팅, GCM 설정 ] (0) | 2018.12.18 |
---|---|
android GCM 클라이언트, 서버 완벽 구현 3 [ 클라이언트 셋팅, GCM 설정 ] (0) | 2018.12.18 |
android GCM 클라이언트, 서버 완벽 구현 1 [ 사전 준비 ] (0) | 2018.12.18 |
안드로이드 회전 막기 (0) | 2018.12.10 |
간단한 웹뷰 컴포넌트의 이해와 최적화 (0) | 2018.12.10 |