반응형
1. C2DM 이란?
- C2DM(Cloud To Device Message)는 안드로이드 2.2 프로요부터 생겨난 API로 개발자들이 서버와 모바일 어플리케이션간에 데이터를 쉽게 싱크할 수 있도록, 서버쪽 에서 안드로이드 폰 상의 어플리케이션으로 데이터를 손쉽게 전달할 수 있도록 도와준다. 쉽게 말하면 서버쪽에서 app이 설치되어있는 폰으로 push방식으로 원하는 메시지를 전달할 수 있게 해준다. 아이폰의 그것과 같다. 현재 C2DM이 나오기 전까지는 클라이언트가 서버쪽을 방문하여 메시지를 요구하는 polling기법을 통하여 실시간 메시징을 했는데, 이 API가 추가되면서 일반 서드파티 개발자도 손쉽게 프로그래밍을 개발할 수 있게 되었다.
2. 준비
- 먼저 push를 사용하기 위해선 구글에 신청을 해야 한다. 예전에는 신청 후 승인 메일이 올 때까지(승인 메일이 와야 사용할 수 있다.) 일주일이 걸렸다고 하는데 요즘엔 5분이면 온다.
링크 : http://code.google.com/intl/ko-KR/android/c2dm/signup.html
여기서 중요한 부분이 바로 첫번째 부분인 Package name of your Android app 이다. 자신이 만들고 있는 app의 package명을 정확히 적어야 한다. 대충 아무렇게 적거나 잘 못 적을시 사용할 수 없다.
C2DM을 사용하기 위해서는 개발자ID(구글개정), app ID(패키지이름), 등록ID(특정장치를 식별하는 ID), 구글사용자계정, 인증토큰값이 필요하다. 이중 등록ID는 다른 사람의 등록ID를 알 수 있다면 그 사람에게 메시지를 보낼 수 있다. 하지만 이것은 사용자가 등록ID를 신청할 때 마다 바뀐다.
위의 그림을 잠깐 설명하면 app을 실행하여 개발자 ID와 appID를 C2DM서버에 전송하여 등록ID를 발급 받는다. 이 등록ID는 등록할 때 마다 다르다. 그다음 메시지를 쓰고 전송을 누르면 먼저 C2DM에 인증을 요청해야 한다. 이 때 개발자ID가 필요하다. 인증이 되면 등록ID, 인증토큰값, 보낼 메시지 등을 push에 담아 상대방 핸드폰에 보내게 된다.
3. 핵심 코드 & 설명
- C2DM 등록 ID 발급을 위해서
//C2DM 등록ID 발급
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
//App ID
//App ID
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
//개발자 ID
//개발자 ID
registrationIntent.putExtra("sender", "xxxxxxxx@gmail.com");
//서비스 시작(등록ID발급받기)
//서비스 시작(등록ID발급받기)
startService(registrationIntent);
// 위에서 지정한 "app"와 "sender"은 맘대로 지정하시는게 아니라 구글에서 필요한 변수명들입니다.
위의 코드로 등록 ID를 받을 수 있다. 그리고 나서
// 메시지를 보낼때 sender(발급받은 ID, 토큰인증값, 메시지)
sender(C2dm_BroadcastReceiver.registration_id, getAuthToken(), "보낼 메시지");
.......
public void sender(String regId,String authToken,String msg) throws Exception{
StringBuffer postDataBuilder = new StringBuffer();
//등록ID
postDataBuilder.append("registration_id="+regId);
postDataBuilder.append("&collapse_key=1");
postDataBuilder.append("&delay_while_idle=1");
//보낼 메세지
//보낼 메세지
postDataBuilder.append("&data.msg="+URLEncoder.encode(msg, "UTF-8"));
//메시지 이외에도 다른 변수들도 보낼 수 있다.
//ex)&data.phone="+URLEncoder.encode(phone, "UTF-8"
//메시지 이외에도 다른 변수들도 보낼 수 있다.
//ex)&data.phone="+URLEncoder.encode(phone, "UTF-8"
//받을 때는 intent.getExtras().getString("msg"); 이렇게 받는다. 또는 msg대신 phone
//이렇게....
//이렇게....
byte[] postData = postDataBuilder.toString().getBytes("UTF8");
URL url = new URL("https://android.apis.google.com/c2dm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", Integer.toString(postData.length));
conn.setRequestProperty("Authorization", "GoogleLogin auth=" + authToken);
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
conn.getInputStream();
}
public String getAuthToken() throws Exception{
String authtoken = "";
StringBuffer postDataBuilder = new StringBuffer();
//똑같이 써준다.
postDataBuilder.append("accountType=HOSTED_OR_GOOGLE");
//개발자 구글 ID
//개발자 구글 ID
postDataBuilder.append("&Email=xxxxxx@gmail.com");
//개발자 구글 비밀번호
//개발자 구글 비밀번호
postDataBuilder.append("&Passwd=xxxxxx");
postDataBuilder.append("&service=ac2dm");
postDataBuilder.append("&source=test-1.0");
byte[] postData = postDataBuilder.toString().getBytes("UTF8");
URL url = new URL("https://www.google.com/accounts/ClientLogin");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", Integer.toString(postData.length));
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
authtoken = authLine.substring(5, authLine.length());
return authtoken;
}인증ID와 토큰값을 구해서 메시지만 push에 태워서 보낸다.
AndroidManifest.xml에도 등록이 필요하다.
<!-- C2DM을 이용한 메시지 SEND Permission -->
<receiver android:name=".C2dm_BroadcastReceiver"
<receiver android:name=".C2dm_BroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- C2DM을 이용한 메시지 RECEIVE intent-filter -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="org.mash.c2dm"/>
</intent-filter>
<!-- C2DM을 이용하기 위해서 ID등록 intent-filter -->
<!-- C2DM을 이용하기 위해서 ID등록 intent-filter -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="org.mash.c2dm"/>
</intent-filter>
</receiver>
..........
<!-- 여기서 protectionLevel 이라는 놈은 normal/dangerous/signature/signatureOrSystem 이렇게 3가지로 구분하는데, normal과 dangerous로 선언된 것은 그냥 어떤 application 이든 맘대로 사용할 수 있지만, signature가 들어가는 것으로 선언되어 있으면, 이 permission을 사용하기 위해서는 이 permission을 선언한 패키지와 같은 certicate로 application이 signature 되어야 한다. 이에 대한 설명은 다음에 하기로 한다. 절대 귀찮아서가 아님...-->
..........
<!-- 여기서 protectionLevel 이라는 놈은 normal/dangerous/signature/signatureOrSystem 이렇게 3가지로 구분하는데, normal과 dangerous로 선언된 것은 그냥 어떤 application 이든 맘대로 사용할 수 있지만, signature가 들어가는 것으로 선언되어 있으면, 이 permission을 사용하기 위해서는 이 permission을 선언한 패키지와 같은 certicate로 application이 signature 되어야 한다. 이에 대한 설명은 다음에 하기로 한다. 절대 귀찮아서가 아님...-->
<permission android:name="org.mash.c2dm.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="org.mash.c2dm.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET"/>
다음으로 메시지가 도착하게 되면 BroadcastReceiver를 등록하였기 때문에 이 클래스를 상속받은 클래스의 Override한 onReceive함수가 이벤트를 받게되고 여기서
@Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
//등록ID를 받는 부분
handleRegistration(context, intent);
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")){
//push된 메시지가 도착했을 때
}
}
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")){
//push된 메시지가 도착했을 때
}
}
private void handleRegistration(Context context, Intent intent) {
registration_id = intent.getStringExtra("registration_id");
System.out.println("registration_id====>"+registration_id);
if (intent.getStringExtra("error") != null) {
//에러
} else if (intent.getStringExtra("unregistered") != null) {
//미등록
} else if (registration_id != null) {
//등록 아이디가 안왔을 때(안오는 경우도 가끔있다.)
}
}
많이들 사용하는 카카오톡도 이걸로 할 수 있을듯 하다. 여하튼 C2DM은 유용하다.
반응형
'Android' 카테고리의 다른 글
Android 이메일&MMS 로 이미지 파일 첨부 보내기 (0) | 2011.10.21 |
---|---|
Android 미디어스캔 (0) | 2011.10.21 |
버튼에 이미지와 텍스트 (0) | 2011.10.17 |
Intro 활ㅋ용ㅋ (0) | 2011.10.13 |
Facebook 연동 방법 (0) | 2011.10.13 |