티스토리 뷰

728x90

1. 개요

 


  GCM이란 Google Cloud Messaging Service로 구글이 제공하고 있는 API 기능 중 하나입니다. 직접 Sender가 Receiver에게 메시지를 보내는 것이 아니라 GCM에게 메시지를 보내고 해당 메시지를 GCM이 다시 Receiver에게 전달해 줍니다.


  추가로 기존 eclipse에서 제공하던 Google Cloud Messaging기능이 IDE가 Andoird Studio로 변경되면서 Ant 기반 빌드 방식을 Gradle로 변경하였습니다. 즉 기존 프로젝트의 hash키를 등록하는 방식이 아닌 프로젝트 내 build.gradle에 GCM을 사용한다는 문장을 추가함으로써 쉽게 GCM을 사용하실 수 있습니다.


  Sender가 GCM에게 메시지를 전달하는 방법에는 php를 이용한 방식과 node.js를 이용한 방식이 있는데, 이번 글에서는 php를 이용하여 GCM을 구현하였습니다.


 아래 영상은 완성본 영상입니다.  웹 페이지(sender)에서 핸드폰(receiver)에게 메시지를 보내며 핸드폰은 해당 메시지를 수신하여 Notification으로 알려줍니다.



2. 프로젝트 생성하기

 

  우선 빈 프로젝트를 생성합니다. 생성시 Application name에 _(언더바)를 포함한 특수문자나 한글이 들어가지 않도록 합니다.




3. 앱 등록하기

 

  GCM 서비스를 이용하기 위해서는 구글 개발자 포럼에 GCM 기능을 사용하겠다고 등록을 해야합니다. - https://developers.google.com/cloud-messaging/


 우선 로그인을 하시고 해당 페이지의 우측 상단의 TRY IT ON ANDROID을 클릭합니다.



  이전에 생성한 어플리케이션을 등록시킬것이기 때문에 add Cloud Messaging to your existing app을 누릅니다. 



  어느정도 페이지를 내려가시다 보면 GET A CONFIGURATION FILE버튼이 보이실 겁니다. 해당 버튼을 눌러 등록 페이지로 넘어갑니다.



  기존에 생성한 프로젝트의 정보를 입력합니다.



ENABLE GOOGLE CLOUD MESSAGING버튼을 눌러 활성화를 시켜줍니다. 



  서비스 이용에 필요한 json파일을 받기위해 아래 Generate configuration files버튼을 누릅니다.



  이전에는 Server API Key와 Sender ID를 따로 메모해 두었으나 현재에는 이 정보들이 들어있는 json파일을 다운받아 해당 안드로이드 프로젝트에 추가합니다. json파일을 열어보시면 Server API Key와 Sender ID 정보가 들어 있을 겁니다.



4. 안드로이드 프로젝트 설정 하기

 

  우선 다운받은 google-services.json 파일을 위 사진과 같은 위치에 복사합니다.



이후 app->src->build.gradle
상단에 apply plugin: 'com.google.gms.google-services'
하단에 dependencies에 compile 'com.google.android.gms:play-services-gcm:8.3.0'를 추가합니다.



  추가로 app->gradle->build.gradledependencies에 classpath 'com.google.gms:google-services:1.5.0-beta2'를 추가합니다.
모든 추가가 끝나시면 오른쪽 상위 Sync Now 디버깅을 한번해주시기 바랍니다.


 지금 한 프로젝트 설정은 https://developers.google.com/cloud-messaging/android/client#add-config에 자세히 설명하고 있습니다. 참고하시기 바랍니다.



5. Sample Code(Android)

 

  해당 셈플 코드는 구글에서 제공하고 있는 셈플코드를 변경하여 만든 것입니다. 구글 셈플 코드는 https://github.com/googlesamples/google-services/tree/master/android/gcm에 들어가시면 다운받으실 수 있습니다.


  우선 일반 클레스(자바) 파일 3개를 추가 하여 위 사진처럼 만듭니다. Service 클레스를 생성하셔도 됩니다. 저의 셈플 코드는 구글 셈플코드보다 클레스가 하나 적습니다. 


   1. MainActivity : Activity class입니다.

   2. InstanceIDListenerService : service class입니다.

   3. RegistrationIntentService : Intent service class입니다.

   4. GCMListenerService : service class입니다.


 진행을 하기전 Service와 Notification이 무엇인지 모르신다면 아래 주소로 가셔서 한번 보셨으면 합니다.

  Notification 설명 : http://twinw.tistory.com/48

  Service 설명 : http://twinw.tistory.com/49

  Service + Notification 통합 예제 :  http://twinw.tistory.com/50



1. Manifests.xml

  Manifests.xml의 상단에 gcm을 사용하기 위한 permission을 추가합니다. 여기서 주의하실 것이 <project name>을 자신의 프로젝트 이름으로 변경해 주셔야 합니다.


  메시지를 수신받기 위한 receiver를 추가합니다.


  생성한 클레스가 service class이며 사용한다고 정의해 줍니다. 여기서도 주의하실 것이 <project name>을 자신의 프로젝트 이름으로 변경해 주셔야 합니다.


  Manifests.xml의 풀 코드입니다.


2. MainActivity.java

  MainActivity입니다. BroadcastReceiver를 이용하여 RegistrationIntentService에서 보낸 로컬 메시지를 수신하여 버튼의 글과 색상을 변경합니다.


3. activity_main.xml

  MainActivity의 xml 파일입니다.


4. InstanceIDListenerService.java

  gcm에서 제공하는 Service를 extends하고 있습니다.


5. RegistrationIntentService.java

  Device의 Id인 token을 등록합니다. 또한 LocalBroadcastManager를 이용하여 등록 완료를 MainActivity에게 알려줍니다.


6. GcmListenerService.java

  GCM서버에서 보낸 message를 수신하는 service입니다. 받은 메세지를 Notification으로 알려줍니다.



6. Sample Code(Sender-html & php)

 

  Sender는 html로 구현한 웹 페이지와 구글 서버로 데이터를 전송할 php로 구현하였습니다. 아마 서버 프로그램에 아무런 설정을 하지 안으시고 동작을 시키시면 curl에 관한 오류가 발생할 것입니다. 해당 오류는 서버 프로그램의 설정에서 php_curl.dll을 사용한다고 변경해주시면 됩니다. 이 부분은 유저 분들의 서버 프로그램이 각각 다를 것이기 때문에 설명하지 않겠습니다.

그리고 테스트는 loop back(127.0.0.1)이나 개인 주소로 하여 테스트 해주시기 바랍니다.


1. gcmsender.html


2. gcmsender.php


  해당 코드로 테스트 할 시, 기본적인 GCM API 키와 같은 데이터를 php에 작성해 주셔야합니다. 또한 php에 작성해야하는 Device Token ID는 안드로이드에서 등록 번튼을 누르고 로그 검색을 통해 쉽게 알 수있습니다. 



  추가로 100개의 디바이스에게 메시지를 전송한다고 가정했을 때 php에 Token ID를 100개 적어 한번에 보내는 것이 100번 보내는 것보다 빠릅니다.

댓글
  • 프로필사진 cosmos 안녕하세요. 질문이 있습니다.
    위 과정에서 생긴 토큰은 폰마다 다른 것인가요? 예를 들어 어떤 앱을 설치한 사용자가 10명이라면 각각 사용자 마다 다른 토큰을 생성해서 그 토큰을 받아서
    서버에서 각각 10번에 걸쳐 푸시알림을 전송해야 하는 것인가요?
    2016.06.07 21:38
  • 프로필사진 White Whale 예 사용자 각각 토큰이 생깁니다.
    안드로이드(클라이언트) 앱 개발 시 구글에 등록된 프로젝트 키를 집어 넣습니다. 그리고 토큰 생성에서 해당 프로젝트에 요청을 하고 각각 클라이언트에 대한 토큰을 부여 받습니다. 따라서 해당 클라이언트에 대한 모든 유저에게 알림을 보내기 위해서는 모든 유저의 토큰을 서버가 알고 있어야 합니다.
    위 예제에서는 테스트를 하기위해서 직접 입력을 해서 하지만 실제 앱에서는 최초 한번 서버에 토큰을 저장하여 토큰을 관리합니다. 또한 토큰은 한번 발급받으면 구글 프로젝트에 등록되어 있기 때문에 재발급을 하여도 같은 토큰이 발급 받게 됩니다.
    2016.06.07 21:45 신고
  • 프로필사진 user 안녕하세요 질문이 있습니다.
    정리해주신대로 GCM 을 진행 하였는데 토큰을 불러오지 못하거든요
    혹시 예상하시는 문제가 있을까요?
    오류는 전혀 나지 않습니다. 프로그래스 바만 움직이네요 ㅠㅠㅠ
    2016.08.02 16:45
  • 프로필사진 White Whale cckr2@naver.com 로 프로젝트 보내주실수 있나요? 프로젝트를 보는게 가장 빠르게 해결해 드릴수 있을꺼 같아서요 2016.08.02 17:12 신고
  • 프로필사진 user gradle 문제 였네요;;;; 구글링 하면서 해결했습니다!
    너무 좋은 예제 인데 지식이 부족해서 잘 활용을 못했었네요 ㅠㅠ 답글 달아주셔서 감사드려요!
    늦었지만 좋은 하루 되세요 ㅎㅎ
    2016.08.02 18:48
  • 프로필사진 고돌이님 안녕하세요. 질문이 있는데요.

    GCM 을 구현하여 테스트 하는데 API 키, SenderID, RegID 모두 정상등록 되었고
    PHP로 메세지를 Send 하는데 디바이스에는 GCM 메시지가 수신 되는데 해당 메시지를 클릭하여 살펴보면
    내용이 없습니다. 제목도 제가 설정한 제목이 아니라 기본 설정되어진 "GCM Message"라고 되어 있습니다.

    안드로이드 스튜디오에서 로그살펴보면 아래와 같이 나옵니다.
    즉, SenderID는 정상 수신하는데 Message는 null 값이 되어 버립니다.

    [아래]
    08-11 14:48:13.435 8812-692/gcm.play.android.samples.com.gcmquickstart D/MyGcmListenerService: From: 5867********
    08-11 14:48:13.435 8812-692/gcm.play.android.samples.com.gcmquickstart D/MyGcmListenerService: Message: null

    안드로이드 부분은 위의 GCM 사이트에서 샘플 다운 받아 사용하였고
    PHP 부분은 위의 PHP 그대로 사용하였습니다.
    2016.08.11 15:52
  • 프로필사진 White Whale 내용물을 한글이 아닌 영어로 한번 보내보시길 바랍니다. 저두 언어 인코딩으로 메시지는 넘어가도 데이터가 비었던 경우가 있었거든요 2016.08.11 15:54 신고
  • 프로필사진 고돌이님 답변 감사 합니다. 님 말씀대로 영어로 하니 내용이 들어가네요.

    그럼 php에서 한글 전송은 어떻게 해야 할까요?
    인코딩을 맞추어 줘서 테스트 해봐야 할 것 같네요.
    ㅠㅠ
    2016.08.11 17:07
  • 프로필사진 White Whale 아마 php와 html사이의 통신에서 데이터가 깨져어 빈 데이터가 전달되는 것이라고 저는 예상합니다. 우선 php와 html 언어 인코딩을 같은거로 하시고 php와 html사이 파라메터 전달이 정확히 되는지 확인하시기 바랍니다. 2016.08.11 17:53 신고
  • 프로필사진 지은짱 안녕하세요. 질문이 있습니다.
    알려주신 코드대로 작성했는데 RegistrationIntentService.java에서
    gcm_defaultSenderId 에서 빨간줄 에러가 뜨네요. gradle에 apply plugin: 'com.google.gms.google-services'도 넣어주었고
    app폴더에 google-services.json파일을 복사해서 넣어주었는데도 왜 그런지 모르겠습니다 ㅠㅠ
    에러 뜨는 부분에 마우스를 올려놓으면 cannot resolve symbol 'gcm_defaultSenderId'라고 뜨는데 왜그런걸까요?ㅠㅠ
    2016.08.13 22:35
  • 프로필사진 비밀댓글입니다 2016.09.14 12:48
  • 프로필사진 White Whale 저는 MQTT와 GCM은 다른 서비스 종류이기 때문에 전송이 되지 않을 것이라고 생각합니다.
    GCM은 구글 서비스로 구글 프로젝트 API 키를 이용하여 전송을 합니다. 또한 php 소스코드를 보시면 하나의 Array를 GCM 서버(저의 프로젝트)로 보내는 것을 보실 수 있습니다. 그리고 전달되는 Array는 2차원 배열이며 데이터와 목적 디바이스의 토큰이 들어가 있습니다. 반대로 MQTT는 MQTT 서버 ip로 토픽과 메세지를 보냅니다. GCM은 메세지를 서버로 보내어 저가 설정한 복수개의 디바이스로 보낼 수 있습니다. 반면에 MQTT는 토픽으로 데이터를 보내며 디바이스가 MQTT 서버로부터 메세지를 전달 받는 것이 아니라 해당 토픽에 접속하여 토픽에 들어오는 메세지를 읽습니다.

    세부적으로 구동원리를 몰라 100% 저가 한 말이 맞다고 할순없지만 저는 위와 같은 이유로 되지 않을 것이라고 생각합니다.
    2016.09.14 22:13 신고
  • 프로필사진 비밀댓글입니다 2016.09.15 04:41
  • 프로필사진 White Whale gcm소개 홈페이지를 둘러보았습니다. FCM으로 GCM에서 다음버전으로 올라가면서 MQTT의 시스템인 topic 전송과 subscribe가 추가되었더라구요. 질문해주신 부분은 $arr[to'] = array();를 하지마시고 바로 $arr['to'] = "Topic"; 으로 해주시는게 맞다고 생각합니다. 또한 json 형태로 변환해서 보내는 것이기 때문에 Array에 넣어 보내신 해도 하나이기 때문에 크게 문제는 없을 듯합니다. 그렇다고 해서 복수의 Topc에 전송이 가능한 것은 아닙니다. 홈페이지를 둘러보며 예시 코드를 보았지만 모두 하나의 토픽이 파라메터로 들어갔었습니다.

    댓글뿐만 아니라 새로운 소식을 남겨주셨는데 저가 직접 테스트를 하여 100% 확실한 답변을 못 드린점 죄송합니다. 추석 잘 보내시기 바랍니다.
    2016.09.15 09:42 신고
  • 프로필사진 sK0506 답변 감사드려요. 고래님도 남은 연휴 즐겁게 보내세요. 2016.09.15 09:46 신고
  • 프로필사진 kyh 안녕하세요 질문이 있습니다.
    정리해주신대로 GCM 을 진행 하였는데 토큰을 불러오지 못합니다
    메일로 제 프로젝트를 보내드렸는데 한번 봐주실수있습니까?
    2016.09.20 12:05
  • 프로필사진 White Whale 메일로 답변드렸습니다. 2016.09.21 11:43 신고
  • 프로필사진 123 안녕하세요 질문이 하나 있는데요.. 제가 푸시토큰을 카카오 푸시api를 이용해서 구현했습니다..

    그리고 진행을 하는데 pushtoken을 전송할때요 엄청 긴 pushtoken값으로 전송을 하면 push가 전송이 되는데

    deviceid로 전송을 하면 InvalidRegistration라는 에러를 전송합니다.

    제가 알기로는 device id로 push를 전송하면 해당 pushtoken값을 구글에서 알아서 찾아서 전송해주는걸로 아는데 제가 틀리게 아는건가요..
    2016.12.11 01:14
  • 프로필사진 White Whale 이부분에 대해서는 저가 해본적이 없는 부분이라 정확한 답변을 드리기가 어렵네요. 죄송합니다. 2016.12.11 22:19 신고
  • 프로필사진 비밀댓글입니다 2017.11.11 21:43
댓글쓰기 폼