옆동네에도(AS) 글을 올리고 왔는데 여기도 강좌게시판이 따로 없네요..
사람들이 제일 많이 보는 게시판이니까 여기에 올릴게요.
 
요번에 C2DM이 GCM으로 정식서비스를 하여서 많은 분들이 혼란을 겪고 있는거 같아
저같은 초보분들 삽질하지 마시라고 가이드를 적어봅니다.
몇몇 블로그에 예제들을 보았지만 제가 하려는것과 속성이 틀려서 결국
되지도 않는 영어실력으로 개발자문서를 보며 만들었습니다. ㅜㅜ
저는 웹페이지를 거치지않고 자바단에서만 동작하게 하였습니다(필요시 웹DB 사용)
여기서 사용되는 소스의 주 타겟은 컨텐츠서비스를 하는 어플입니다.
무슨 말이냐하면 유저들 정보를 가지고 있으면 한꺼번에 푸쉬하는거죠(이벤트알림이나 공지사항 등등)
여기선 간단히 설명드리고 자세한건 첨부파일을 받아서 봐주세요.
-------------------- GCMMain.java --------------------
 private static final String TAG = "GCM";
 private static final String  PASSWORD = "1111";
 //자신의 Project ID 를 넣어주세요
 private static final String  SENDER_ID = "자신의 프로젝트 아이디"; 
private EditText managerPassword;
private Button managerButton;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//GCM 등록여부
final String regId = GCMRegistrar.getRegistrationId(this);
//등록된 ID가 없으면 ID값을 얻어옵니다
if (regId.equals("") || regId == null) {
GCMRegistrar.register(this, SENDER_ID);
}else{
Log.w(TAG, "Already Registered : " + regId);
}
setInit();
}
-----
-------------------------------------------------
GCMMain.java 에서는 위에 SENDER_ID에 자신의 Project ID를 넣어주시면 됩니다.
-------------------- GCMIntentService.java --------------------
 private static final String TAG = "GCM";
 private static final String  INSERT_PAGE = "http://자신의 서버  아이피/insert_registration.php";
 private static final String SENDER_ID =  "자신의 프로젝트 아이디";
 private GCMHttpConnect  httpConnect = null;
 private GCMHttpConnect.Request httpRequest = new  GCMHttpConnect.Request() {

  @Override
  public void OnComplete()  {
   // TODO Auto-generated method  stub
   showToast();
  }
 };
 
 public GCMIntentService()  {
  super(SENDER_ID);
 }
 
@Override
protected void onMessage(Context context, Intent intent) {
if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
showMessage(context, intent);
}
}
@Override
protected void onError(Context context, String msg) {
// TODO Auto-generated method stub
Log.w(TAG, "onError!! " + msg);
}
@Override
protected void onRegistered(Context context, String regID) {
// TODO Auto-generated method stub
if(!regID.equals("") || regID != null){
Log.w(TAG, "onRegistered!! " + regID);
// 단일전송일때 주석처리
// insertRegistrationID(regID);
}
}
@Override
protected void onUnregistered(Context context, String regID) {
// TODO Auto-generated method stub
Log.w(TAG, "onUnregistered!! " + regID);
}

public void showToast(){
Toast.makeText(this, "RegID 등록 완료", Toast.LENGTH_LONG).show();
}

private void showMessage(Context context, Intent intent){
String title = intent.getStringExtra("title");
String msg = intent.getStringExtra("msg");
String ticker = intent.getStringExtra("ticker");

NotificationManager notificationManager = (NotificationManager)context.getSystemService(Activity.NOTIFICATION_SERVICE);

// 해당 어플을 실행하는 이벤트를 하고싶을 때 아래 주석을 풀어주세요
// PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
// new Intent(context, 어플이 처음 시작되는 클래스명.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);


Notification notification = new Notification();
notification.icon = R.drawable.ic_launcher;
notification.tickerText = ticker;
notification.when = System.currentTimeMillis();
notification.vibrate = new long[] { 500, 100, 500, 100 };
notification.sound = Uri.parse("/system/media/audio/notifications/20_Cloud.ogg");
notification.flags = Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(context, title, msg, pendingIntent);

notificationManager.notify(0, notification);
}

public void insertRegistrationID(String id){
httpConnect = new GCMHttpConnect(INSERT_PAGE + "?regID=" + id, httpRequest);
httpConnect.start();

}
-------------------------------------------------------------
GCMIntentService.java 에서는 INSERT_PAGE와 SENDER_ID가 있습니다.
SENDER_ID는 GCMMain.java 와 같이 자신의 Project ID를 넣어주면 됩니다.
INSERT_PAGE에는 메세지를 일괄전송시에 RegID값들을 DB에서 불러오기 위한 서버주소입니다.
서버가 없고 RegID값을 DB가 아닌 어플내에서 관리한다면 필요없는 부분입니다.
그 밑에 PendingIntent 에서 주석으로 된 부분에 어플이 시작되는 클래스명을 적어주면
메세지 수신시 인디케이터에 메시지가 뜨면서 클릭시 해당 액티비티를 실행시키는 겁니다.
그리고 insertRegistrationID(String id)부분은 마찬가지로 웹서버에서 DB데이터를 뽑아오는
함수입니다. "?regID=" 부분은 파라메터 인자값이고요. 역시 서버가 없다면 주석처리 하시면 됩니다.
-------------------- GCMSendMessage.java --------------------
 private Sender    gcmSender;    //GCM Sender
 private Message    gcmMessage;   //GCM Message
 private Result     gcmResult;    //GCM  Result(단일 전송)
 private MulticastResult  gcmMultiResult;  //GCM Multi  Result(일괄 전송)
 
 //일괄전송에 필요한 List 변수
 private List<String>  registrationIds = new ArrayList<String>();
 //단일전송에 필요한 변수
 private  String     registrationId = "이곳에 RegId를  입력하세요";
 //DB에서 RegID를 가져오기 위해 만들어진 서버 페이지 주소 
 private static  final String SELECT_PAGE = "http://자신의 서버  아이피/select_registration.php";
 //파싱하기 위해 데이터를 담을 변수
 private static  String JSON = null;
 //개발자 콘솔에서 발급받은 API Key
 private static String   API_KEY = "자신이 발급받은 API KEY를 입력하세요";
 //메세지의 고유 ID(?)정도로 생각하면 됩니다. 메세지의 중복수신을 막기 위해 랜덤값을 지정합니다
 private static String   COLLAPSE_KEY = String.valueOf(Math.random() % 100 + 1);
 //기기가 활성화 상태일 때  보여줄 것인지. 
 private static boolean  DELAY_WHILE_IDLE = true;
 //기기가 비활성화  상태일 때 GCM Storage에 보관되는 시간
 private static int   TIME_TO_LIVE = 3;
 //메세지  전송 실패시 재시도할 횟수
 private static int    RETRY = 3;
 
 private EditText  pushTicker;
 private EditText pushTitle;
 private EditText  pushMessage;
 private TextView pushLength;
 
 private Button  pushShow;
 private Button pushTrans;
 
 @Override
 public void  onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.send_message);

     setLayout();
//     단일전송시에는 주석처리
//     getJson(SELECT_PAGE);
//     단일전송시에는 주석처리
//     getToken();     
 }
 
 public void setMessage(){
  gcmSender = new  Sender(API_KEY);
  gcmMessage = new Message.Builder()
      .collapseKey(COLLAPSE_KEY)
     .delayWhileIdle(DELAY_WHILE_IDLE)
      .timeToLive(TIME_TO_LIVE)
     .addData("ticker",  pushTicker.getText().toString())
     .addData("title",  pushTitle.getText().toString())
     .addData("msg",  pushMessage.getText().toString())
     .build();
 }
 
 public void  sendMessage(){
  //일괄전송시에 사용
//  try {
//   gcmMultiResult =  gcmSender.send(gcmMessage, registrationIds, RETRY);
//  } catch (IOException  e) {
//   Log.w(TAG, "IOException " +  e.getMessage());
//  }
//  Log.w(TAG, "getCanonicalIds : " +  gcmMultiResult.getCanonicalIds() + "\n" + 
//    "getSuccess : " +  gcmMultiResult.getSuccess() + "\n" + 
//    "getTotal : " +  gcmMultiResult.getTotal() + "\n" + 
//    "getMulticastId : " +  gcmMultiResult.getMulticastId());

  //단일전송시에 사용
try  {
   gcmResult = gcmSender.send(gcmMessage, registrationId, RETRY);
  }  catch(IOException e) {
   Log.w(TAG, "IOException " +  e.getMessage());
  }
  Log.w(TAG, "getCanonicalIds : " +  gcmResult.getCanonicalRegistrationId() + "\n" + 
    "getMessageId : " +  gcmResult.getMessageId());
 }
-----------------------------------------------------------------
메세지를 보내는 GCMSendMessage.java 부분입니다.
String registrationId 는 단일전송시에 직접 입력하는 부분입니다. 등록시 얻은 RegID를 적어주시면 됩니다.
List<String> registrationIds 는 일괄전송시에 사용되는 변수로 onCreate에서
데이터를 얻어오고 그 수만큼 add하고 있습니다.
SELECT_PAGE는 DB에서 RegID들을 얻어오기 위한 서버페이지입니다.
역시 서버가 없다면 무시해도 됩니다.
API_KEY는 Api Console 센터에서 발급받은 Key입니다. 뭐 Project ID와 API_KEY 는 전부 아시리라 믿습니다.
---------- 정리 ------------
- 단일전송일 경우(한명에게 보내고자 할 경우 or 테스트용)
위에서 말한 API_KEY, SENDER_ID, RegID 변수에 자신의 값들을 넣어주시고 테스트하시면 됩니다.
- 일괄전송일 경우
(개인 서버가 있는경우)
위 소스에 있는 주석들을 풀어준 후 자신의 서버주소를 적어주시면 됩니다.
(개인 서버가 없는경우)
RegID 값들을 알 수 있다면 List에 직접 add하여 주시거나
SharedPreferences를 이용하여 데이터를 불러와 add하셔도 됩니다.
혹시 서버페이지를 만드시려고 하는분이 있으시면 참고되시라고 같이 올렸습니다.
---------------------------
--------- 필수로 해야할것들 ---------
이 소스를 이용하여 자신의 프로젝트에 적용시킬 때 주의하실점이 있습니다.
- Manifest GCM관련 퍼미션등록 여부와 리시버 등록 여부 확인 (첨부된 프로젝트와 비교하세요)
- 각종 퍼미션 (WAKE_LOCK, INTERNET, GET_ACCOUNTS, VIBRATE) <- 요거안해주면 고생많이 합니다.
- !!!GCM라이브러리 추가!!!(gcm.jar gcm-server.jar json_simple-1.1.jar)
제일 중요합니다. 꼭 libs폴더에 넣어서 빌드패스에 추가하셔야합니다.
특히 json_simple-1.1.jar 요놈 없으면 NodefClassException이라는 상큼한 에러가 나옵니다.
라이브러리는 다음과 같은 경로에 있습니다.(개발환경 마다 경로가 다를 수 있습니다)
SDK/android-sdk/extras/google/gcm/gcm-client/dlist/gcm.jar
SDK/android-sdk/extras/google/gcm/gcm-server/dlist/gcm-server.jar
SDK/android-sdk/extras/google/gcm/gcm-server/lib/json_simple1.1.jar
-----------------------------------
이상으로 글을 마칩니다. 모르시는 부분이 있으면 코드 조금만 분석해보시면
금방 알 수 있을거에요. ㅎㅎ 워낙 허접한 코드라서..
저같은 초보분들에게 바칩니다. 해보시고 잘되시면 칭찬한번씩만 해주세요.
회사에서 하라는 일은 안하고 이런짓하고 있어요.