기다리던 롬! 이제 플래싱 할시간!!
여러가지 롬들 사용해봤지만 Nexus S용 ICS롬은 DrewGaren ROM이 제일 맘에 든다.
구글 지원들이 Official ICS ROM 사용중이라고 하니 공식 릴리즈 되기 전까지는 큰 문제 없으면 이 롬에 정착 할 듯. <-- 플래싱 해보니.. 너무 문제가 많다. 다시 Beta ROM으로 복원 -_-;
DrewGaren.com: Nexus S - ICY+ S version 1.0: Nexus S Rom - ICY+ S version 1.0 The first stable release of Android 4.0.1 Ice Cream Sandwich from DrewGaren. Minus, fully enabled camera e...
Tuesday, December 13, 2011
Friday, December 9, 2011
Android C2DM client 예제
준비물 : c2dm account(파이썬으로 c2dm서버 만들기 포스팅 참조)
우선 Manifest file의 Code
중요한 부분:
15~ 28 line <-com.leehack.c2dmtest.push.C2DMReceiver 등록
31~36 line <- C2DM을 사용할 수 있도록 어플에 permission부여
C2DMReceiver.java: 리시버 작성
package com.leehack.c2dmtest.push;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;
public class C2DMReceiver extends BroadcastReceiver {
static String registration_id = null;
private Context mContext;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
"com.google.android.c2dm.intent.REGISTRATION")) {
handleRegistration(context, intent);
} else if (intent.getAction().equals(
"com.google.android.c2dm.intent.RECEIVE")) {
handleMessage(context, intent);
}
}
//서버에 등록이 되면 Registration_id를 C2DM서버에서 보내준다. 받은 이 ID를 별도로 구성한 서버에 보내야 한다.
private void handleRegistration(Context context, Intent intent) {
String registration = intent.getStringExtra("registration_id");
if (intent.getStringExtra("error") != null) {
// Registration failed, should try again later.
} else if (intent.getStringExtra("unregistered") != null) {
registration = null;
} else if (registration != null) {
registration_id = registration;
mContext = context;
SharedPreferences sp = mContext.getSharedPreferences("com.leehack.c2dmtest", Activity.MODE_PRIVATE);
SharedPreferences.Editor ed = sp.edit();
ed.putString("registration_id", registration_id);
ed.commit();
Toast toast = Toast.makeText(context, "Registration Id\n" + registration_id,
Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 150);
toast.show();
Log.d("C2DMReceiver", "c2dm registered");
}
}
//메세지가 도착하면 토스트로 도착한 메세지를 보여줌
private void handleMessage(Context context, Intent intent) {
String c2dm_msg = intent.getExtras().getString("msg");
System.out.println("c2dm_msg======>" + c2dm_msg);
Toast toast = Toast.makeText(context, "c2dmMessage\n" + c2dm_msg,
Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 150);
toast.show();
}
}
PushHelper.java: c2dm 서버에 Register/Unregister 메소드 작성
package com.leehack.c2dmtest.push;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
public class PushHelper {
final static String c2dmDevId = "c2dm에 등록한 account";
public static void c2dmRegister(Context context){
SharedPreferences sp = context.getSharedPreferences("com.leehack.c2dmtest", Activity.MODE_PRIVATE);
if(sp.getString("registration_id", null) != null)
return;
Intent registrationIntent = new Intent(
"com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app",
PendingIntent.getBroadcast(context, 0, new Intent(), 0));
registrationIntent.putExtra("sender", c2dmDevId);
context.startService(registrationIntent);
}
public static void c2dmUnregister(Context context){
Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
unregIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0));
context.startService(unregIntent);
}
}
C2DM_TESTActivity.java: Register와 Unregister버튼의 동작을 정의
package com.leehack.c2dmtest;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import com.leehack.c2dmtest.push.PushHelper;
public class C2DM_TESTActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PushHelper.c2dmRegister(C2DM_TESTActivity.this);
}
});
findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PushHelper.c2dmUnregister(C2DM_TESTActivity.this);
}
});
}
}
앞으로 해야 할일!
1. 구글의 C2DM과 통신한 Push Server 구성
2. Register를 한 후 C2DMReceiver를 통해 C2DM 서버로 부터 전달받은 Registration_ID를 구성한 Push Server로 전달하는 로직 구성
(파이썬으로 c2dm서버 만들기 포스팅을 참조하면 1번은 해결될 것이고 2번만 추가로 구성하면 된다)
Python으로 c2dm server 만들기
1. http://code.google.com/intl/ko-KR/android/c2dm/ 에서 c2dm 서비스에 sign-up
(gmail account를 새로 만들어서 가입하는 것이 좋다. - 실제로 이 account정보를 클라이언트 및 서버에 모두 넣어야 하고 더구나 서버에는 패스워드정보도 필요하기 때문)
2. 가입하면 E-mail로 가입한 Account로 서비스가 Enable되었다는 내용의 메일이 옮(보통 하루안에 오고 늦어도 몇일 사이에는 오는 듯)
여기까지 준비 완료! 아래는 실제 파이썬 코드 시작!!
http://blog.boxedice.com/2010/10/07/android-push-notifications-tutorial/ 에 있는 예제코드인데 제대로 돌지 않아서 약간의 수정만 했음.
이미 눈치 채셨겠지만 실제 사용시에는 78라인부터만 따로 가져가서 원하는 곳에 사용하면 된다. collapseKey를 1로 고정해두고 사용하면 c2dm메세지가 동일한 단말에 동일한 메세지를 계속 적으로 보낼 경우 중간중간 빼먹는 경우가 생긴다. 구글에서 중복된 메세지 전송을 방지하게 넣어둔 코드임. 중복으로 보내는 메세지라도 단말에 꼭 전송이 되어야 하는 메세지라면 collapseKey를 increase하면서 보내는 것이 상책!
(gmail account를 새로 만들어서 가입하는 것이 좋다. - 실제로 이 account정보를 클라이언트 및 서버에 모두 넣어야 하고 더구나 서버에는 패스워드정보도 필요하기 때문)
2. 가입하면 E-mail로 가입한 Account로 서비스가 Enable되었다는 내용의 메일이 옮(보통 하루안에 오고 늦어도 몇일 사이에는 오는 듯)
여기까지 준비 완료! 아래는 실제 파이썬 코드 시작!!
import urllib, urllib2
class ClientLoginTokenFactory():
_token = None
def __init__(self):
self.url = 'https://www.google.com/accounts/ClientLogin'
self.accountType = 'GOOGLE'
self.email = 'c2dm에 가입한 메일주소'
self.password = 'c2dm에 가입한 메일주소의 패스워드'
self.source = 'replstory-replstory-0'
self.service = 'ac2dm'
def getToken(self):
if self._token is None:
# Build payload
values = {'accountType' : self.accountType,
'Email' : self.email,
'Passwd' : self.password,
'source' : self.source,
'service' : self.service}
# Build request
data = urllib.urlencode(values)
request = urllib2.Request(self.url, data)
# Post
response = urllib2.urlopen(request)
responseAsString = response.read()
# Format response
responseAsList = responseAsString.split('\n')
self._token = responseAsList[2].split('=')[1]
return self._token
class C2DM():
def __init__(self):
self.url = 'https://android.apis.google.com/c2dm/send'
self.clientAuth = None
self.registrationId = None
self.collapseKey = None
self.data = {}
def sendMessage(self):
if self.registrationId == None or self.collapseKey == None:
return False
clientAuthFactory = ClientLoginTokenFactory()
self.clientAuth = clientAuthFactory.getToken()
# Build payload
values = {'registration_id' : self.registrationId,
'collapse_key' : self.collapseKey}
# Loop over any data we want to send
for k, v in self.data.iteritems():
values['data.' + k] = v
# Build request
headers = {'Authorization': 'GoogleLogin auth=' + self.clientAuth}
data = urllib.urlencode(values)
request = urllib2.Request(self.url, data, headers)
# Post
try:
response = urllib2.urlopen(request)
responseAsString = response.read()
return responseAsString
except urllib2.HTTPError, e:
print 'HTTPError ' + str(e)
sender = C2DM()
sender.registrationId = 'Android단말기에서 c2dm서버로 부터 받은 고유번호'
sender.collapseKey = 1
sender.data = {'msg':'test'}
response = sender.sendMessage()
print response
9,10,79 라인의 정보만 바꾸고 실행하면 c2dm등록된 단말기로 test라는 푸시 메세지가 날아간다.http://blog.boxedice.com/2010/10/07/android-push-notifications-tutorial/ 에 있는 예제코드인데 제대로 돌지 않아서 약간의 수정만 했음.
이미 눈치 채셨겠지만 실제 사용시에는 78라인부터만 따로 가져가서 원하는 곳에 사용하면 된다. collapseKey를 1로 고정해두고 사용하면 c2dm메세지가 동일한 단말에 동일한 메세지를 계속 적으로 보낼 경우 중간중간 빼먹는 경우가 생긴다. 구글에서 중복된 메세지 전송을 방지하게 넣어둔 코드임. 중복으로 보내는 메세지라도 단말에 꼭 전송이 되어야 하는 메세지라면 collapseKey를 increase하면서 보내는 것이 상책!
Subscribe to:
Posts (Atom)

