차근차근/Android

GCM 사용하기 2 (단말에 GCM 구현하기)

예쁜꽃이피었으면 2014. 7. 30. 23:39

http://blog.daum.net/mailss/31

안드로이드 단말에서 GCM 푸시를 받을 수 있게 구현하는 방법을 알아보자.

GCM은 구글계정을 필요로 하기 때문에 API 8 (프로요 2.2)이상 요구 된다.


큰 흐름은 단말에 GCM 리시버를 등록하고, GCM 푸시를 받은 후 동작할 백그라운드 서비스를 만든다.


단말에서 앱을 실행하면 GCM 서비스 등록 했는지 체크하여 등록이 안되었으면 등록한 후 등록된 ID를 받는다.


등록된 ID를 서버에 전송한다.


*GCM 소개 : http://developer.android.com/guide/google/gcm/index.html

*가이드 문서 : http://developer.android.com/guide/google/gcm/gs.html


1. GCM 라이브러리 다운로드 받기

SDK 매니저를 실행하여 Extras의 Google Cloud Messaging for Android Library를 다운 받는다.

*현재 Revision 2까지 나왔다.




2. 자신의 프로젝트에 GCM 라이브러리 추가하기

다운로드 받으면 자신이 안드로이드 sdk 설치 폴더(기본은 C:\android-sdk-window)에 들어가 보면

extras 폴더 -> google -> gcm -> gcm-client -> dist 에 들어가 보면 2개의 jar 파일이 있다.

그 중 gcm.jar 파일을 자신의 프로젝트에 추가하면 된다.


자신의 프로젝트에 libs 폴더를 생성 후 그 곳으로 복사한다.

*ADT 버전이 18 이상이면 빌드 패스를 지정하지 않아도 된다. 자동으로 라이브러리를 인식한다.

*ADT 버전이 18 보다 아래 이면 빌드 패스를 지정해야 한다.

*현재 ADT 최신 버전은 20 이다.




 

3. 매니페스트에 GCM 사용 관련 permission과 receiver, service를 등록

*GCM 관련 퍼미션 (패키지는 자신의 앱 패키지 명으로 대체 한다.)

<!-- GCM 관련 퍼미션 -->
<permission android:name="패키지.permission.C2D_MESSAGE" android:protectionLevel="signature" />

<uses-permission android:name="패키지.permission.C2D_MESSAGE" /> 
<!-- GCM 받기 -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM을 받으려면 구글 계정 필요 -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- 메시지 받을 때 wake up 하기 위해 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- 네트워크 접속 권한 -->
<uses-permission android:name="android.permission.INTERNET" />


*GCM 사용 관련해서 안드로이드 버전 제한 (2.2 이상)

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="개발할 api 버전" />


*GCM 리시버 및 서비스 등록

리시버는 코드 상에서 등록하지 말고 메니페스트에 적어서 등록하도록 권장한다.

리시버는 gcm.jar 라이브러리에 포함되어 있다. 구현할 필요 없다.


서비스는 반드시 자신의 기본 패키지에 속해야 하며 이름은 GCMIntentService로 해야 한다.

서비스는 GCMBaseIntentService를 상속받아 구현해야 한다.



<application>

....

<!-- GCM 리시버 -->
<receiver

   android:name="com.google.android.gcm.GCMBroadcastReceiver"

   android:permission="com.google.android.c2dm.permission.SEND" >
   <intent-filter>
      <action android:name="com.google.android.c2dm.intent.RECEIVE" />
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
      <category android:name="패키지" /> <!-- 젤리빈 부터는 category 빼도 된다 -->
   </intent-filter>
</receiver>


<!-- GCM 리시버에서 돌리는 서비스 -->
<service android:name=".GCMIntentService" /><!-- 서비스명 변경하면 안됨 -->

....

</application>


리시버에 다른 intent filter를 등록하지 않아도 앱이 죽어 있어도 푸시를 잘 받아온다.



4. GCMIntentService 구현하기

GCMIntentService는 자신의 앱 기본 패지키에 존재해야 하며 이름을 변경하면 안된다. 또한 public 기본 생성자를 만들어야 한다.

GCMBroadcastReceiver 에서 푸시를 받으면 정해진 이름으로 서비스를 객체를 실행하기 때문에 위의 조건을 만족해야 한다.


GCMIntentService는 GCMBaseIntentService를 상속받아야 한다.


public class GCMIntentService extends GCMBaseIntentService {
    private static final String tag = "GCMIntentService";
    private static final String PROJECT_ID = "구글 api 홈페이지에서 만든 프젝트 ID";

    //구글 api 페이지 주소 [https://code.google.com/apis/console/#project:긴 번호]

   //#project: 이후의 숫자가 위의 PROJECT_ID 값에 해당한다
   

    //public 기본 생성자를 무조건 만들어야 한다.

    public GCMIntentService(){ this(PROJECT_ID); }

   

    public GCMIntentService(String project_id) { super(project_id); }

 

    /** 푸시로 받은 메시지 */
    @Override
    protected void onMessage(Context context, Intent intent) {
        Bundle b = intent.getExtras();

        Iterator<String> iterator = b.keySet().iterator();
        while(iterator.hasNext()) {
            String key = iterator.next();
            String value = b.get(key).toString();
            Log.d(tag, "onMessage. "+key+" : "+value);
        }
    }


    /**에러 발생시*/
    @Override
    protected void onError(Context context, String errorId) {
        Log.d(tag, "onError. errorId : "+errorId);
    }

 

    /**단말에서 GCM 서비스 등록 했을 때 등록 id를 받는다*/
    @Override
    protected void onRegistered(Context context, String regId) {
        Log.d(tag, "onRegistered. regId : "+regId);
    }


    /**단말에서 GCM 서비스 등록 해지를 하면 해지된 등록 id를 받는다*/
    @Override
    protected void onUnregistered(Context context, String regId) {
        Log.d(tag, "onUnregistered. regId : "+regId);
    }
}



5. 앱의 메인 액티비티에 GCM서비스 등록 하는 코드 추가하기

자신의 앱의 메인 액티비티 onCreate 메소드에 gcm 서비스 등록 코드를 추가하자.


GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if("".equals(regId))   //구글 가이드에는 regId.equals("")로 되어 있는데 Exception을 피하기 위해 수정
      GCMRegistrar.register(this, "534641675187");
else
      Log.d("==============", regId);




IntentReceiver com.google.android.gcm.GCMBroadcastReceiver@40233b88 that was originally registered here. Are you missing a call to unregisterReceiver()?


혹시 앱이 죽지 않지만 로그캣에 위와 같은 에러 로그가 출력된다면 gcm 서비스 등록 코드를 자신의 앱 application 클래스의 onCreate로 옮겨주면 된다.




여기까지 작성하면 단말쪽에서는 GCM을 이요한 푸시를 받을 준비가 되었다. 앱을 실행하고 로그를 보면 단말에서 GCM 서비스를 등록한 후 등록 id가 출력 될 것이다. 등록 id를 잘 적어놓자. 나중에 서버 구현시 테스트에 필요하다.

*등록 id는 앱을 삭제 후 다시 설치하고 다시 gcm 서비스를 등록해도 같은 등록 id가 나온다.


실제 앱을 개발할때는 등록 id가 발급되면 자신들의 서비스 서버에 등록 id를 전송 해야 한다.

서버에서는 단말의 등록 id를 가지고 각각의 단말에 푸시 데이터를 구글 푸시 서버에 전송한다.

 

*샘플코드 요청이 있어서 첨부합니다. 샘플에는 PROJECT ID(SEND ID) 값이 빠져 있으니 자신의 프로젝트 ID 값으로 넣어서 테스트 하세요.


전체 샘플 코드 첨부하였습니다.

*글과 자료는 출처만 밝히시면 얼마든지 가져다 쓰셔도 됩니다.

 

 GCMSample.zip



반응형