총 게시물 910건, 최근 0 건 안내 RSS 글쓰기
이전글  다음글  목록 글쓰기
[안드로이드]

구글 GCM Client/Server 완벽 예제(서버페이지 사용X)스압주의

글쓴이 : 피로리 날짜 : 2012-07-18 (수) 15:07 조회 : 19159
글주소 : http://www.androidside.com/B49_best/5347
GCMServerTutorial.zip (1.2M), Down : 100, 2012-07-18 15:07:57
 
  HP 커머셜파트너 온라인24
HP 공인파트너! 저렴한 가격, 친절한 서비스, 실시간 상담, 견적문의 환영
www.online24.co.kr
  HP서버 정데이타
HP서버 ML350 DL360 DL380 특가판매 빠른견적 기술지원 SERVER
www.jungdata.co.kr
  SERVER 넥스트와이즈
SERVER, 슈퍼마이크로 공식수입원, 메인보드, HPC, GPU, IPC
www.nextwise.co.kr
클릭초이스 등록


요번에 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
-----------------------------------
 
이상으로 글을 마칩니다. 모르시는 부분이 있으면 코드 조금만 분석해보시면
금방 알 수 있을거에요. ㅎㅎ 워낙 허접한 코드라서..
 
저같은 초보분들에게 바칩니다. 해보시고 잘되시면 칭찬한번씩만 해주세요.
회사에서 하라는 일은 안하고 이런짓하고 있어요.




질문답변 게시판에서 궁금한 사항을 해결하셨다면, 애써 답변해주신 분께 잘 되었다고 따뜻한 댓글 한마디 남겨주세요.
그리고 답변해주신 분의 글을 '추천' 해주세요.
추천받으신 분에게 1포인트가, 추천하신 분에게도 1포인트가 적립됩니다. ^^

피로리 2012-07-18 (수) 17:20 추천추천 1 반대 0
보통 서버에 있는 웹페이지를 통하여 메세지를 날리게 됩니다.(asp, jsp 등등)
그니까 자신의 웹서버를 한번 거쳐가는거죠
A단말기 -> 웹서버 ->GCM 서버 ->B단말기 이런과정을 거치죠
 
근데 이건 웹페이지없이도 어플자체에서 보낼수있게 했어요.
A단말기 -> GCM 서버 -> B단말기 이렇게요.
php페이지는 DB를 따로 사용하는경우 쓰면 되고요
DB가 없고 사용자의 RegID값을 알면 registrationId 에 넣어서
send하면 됩니다.
바람돌2 2012-07-18 (수) 15:18
 감동입니다 ㅠㅠㅠㅠ
 
안드래도 푸쉬가 어려워서 고생하고 있었는데..
 
여기는 '퍼가요~♥' 이런거 없나요? ㅎㅎ
댓글주소 추천 0 반대 0
바람돌2 2012-07-18 (수) 15:21
개념이 좀 안 잡히는 데 서버가 없을 경우는 만일 제가 만든 어플에서 사용들에게 푸쉬를 어떻게 날릴수 있죠?(예: 카톡)
댓글주소 추천 0 반대 0
     
     
피로리 2012-07-18 (수) 17:20
베플로 선택된 게시물입니다.
보통 서버에 있는 웹페이지를 통하여 메세지를 날리게 됩니다.(asp, jsp 등등)
그니까 자신의 웹서버를 한번 거쳐가는거죠
A단말기 -> 웹서버 ->GCM 서버 ->B단말기 이런과정을 거치죠
 
근데 이건 웹페이지없이도 어플자체에서 보낼수있게 했어요.
A단말기 -> GCM 서버 -> B단말기 이렇게요.
php페이지는 DB를 따로 사용하는경우 쓰면 되고요
DB가 없고 사용자의 RegID값을 알면 registrationId 에 넣어서
send하면 됩니다.
댓글주소 추천 1 반대 0
안드플 2012-07-20 (금) 11:22
좋은 자료 감사합니다.
구글이 좀더 좋게 변하는건 좋지만 자주 바뀌니 익히면 또 익혀야 하고
좀 피곤하네요 ㅎㅎㅎ
좋은글 넘 감사감사
댓글주소 추천 0 반대 0
굼바 2012-07-20 (금) 20:04
이게 메시지 전송해주는 서버쪽 소스인가요?
아니면 통합되있는 소스인가요?
초보인지라 이 소스 말고 다른소스로 해봐도
regID까지는 어떻게 따왔는데 그 이후가 안되네요 ㅠ
댓글주소 추천 0 반대 0
포스원 2012-07-23 (월) 09:58
안그래도 관련 정보 찾느라 이곳저곳 뒤지는 중이었는데
jsp 라서 약간 변경을 해야겠지만 많은 도움이 될것 같습니다.
감사합니다.
댓글주소 추천 0 반대 0
토르웰 2012-07-30 (월) 00:24
정말 감사합니다...
댓글주소 추천 0 반대 0
안드로22드 2012-07-30 (월) 09:09
감사합니다
댓글주소 추천 0 반대 0
알레알레 2012-09-03 (월) 15:20
감사합니다.
댓글주소 추천 0 반대 0
프로세스 2012-11-13 (화) 14:56
감사합니다. 선 추천 후 읽어보렵니다~
댓글주소 추천 0 반대 0
관스틴 2012-12-11 (화) 21:26
완전 최고이십니다.
댓글주소 추천 0 반대 0
관스틴 2012-12-11 (화) 21:49
이곳에 RegId를 입력하세요 
이 부분에는 무엇을 적어줘야하는건가요 ?
어플을 빌드 했는데, Ticker 타이틀 메세지...그 부분도 ㅠ 설명 좀 해주세요

댓글주소 추천 0 반대 0
오로도로동 2013-01-14 (월) 18:54
감사합니다~^^
댓글주소 추천 0 반대 0
겨우리1212 2016-01-22 (금) 13:34

네.감사합니다.

댓글주소 추천 0 반대 0
이전글  다음글  목록 글쓰기

 


Copyright ⓒ www.androidside.com. All rights reserved.
채팅 권한: 글쓰기 1개
2레벨 이상만 대화 가능
공개 채팅: 평일 !(9시 ~ 17시),토,일
안사2 변경사항 보러가기 챗방이 잘 안보이면 크롬에서 접속해주세요
챗방 숨기기 |  챗방 보이기