본문 바로가기
Lecture/Android

안드로이드 GCM 이용과 Third party(jsp) 가이드 - 2부

by 알 수 없는 사용자 2012. 7. 24.
반응형

2부 가이드를 시작하겠습니다. 2부에서는 안드로이드(이하 클라이언트) 코딩에 대하여 설명드리겠습니다. 일단 코딩에 앞서GCM이 구성되는 원리부터 설명드리겠습니다. 그래야만 개발하면서 왜 이렇게 구성해야하는지 이해가 가실겁니다.


GCM의 구성 원리

GCM을 구성하는것은 크게 클라이언트와 GCM 두가지가 있습니다. 하지만 여기에 Third party가 꼽사리를 껴서 구성해도 상관은 없습니다. 클라이언트는 안드로이드 디바이스가 되겠고 GCM은 구글이 지원하는 클라우드 메시징을 전담하는 어떤 실체가 되겠습니다. 그러면 이 두가지가 어떤식으로 동작하는지 설명드리겠습니다.


먼저 안드로이드 디바이스는 각각의 고유 id를 갖고있습니다. 디바이스가 GCM에 등록을 한다고 구글에 요청을 보내면 구글에서는 해당 id를 갖고 어떤 고유 등록id를 생성하여 등록을 요청한 안드로이드 디바이스에 보내고 ,또 구글에서는 등록id를 저장해둡니다. 


왜 구글에서 이 id를 저장하고 또 디바이스에 id를 보내는지는 편지를 보내는 시스템과 비교해보시면 아주 간단하게 이해하실겁니다. 실제로 우리는 우편을 보낼때도 상대방의 주소를 모르면 보내지 못하는게 정상입니다. 이렇듯 구글에서도 푸쉬를 넣을 주소(등록id)를 알지못하면 해당 디바이스에 어떤 메시지도 보낼수가 없습니다. 












또 디바비스에 등록id를 보내주는 이유는 이후 주기적인 등록id 재요청없이 자신의 등록id를 Third party에 보내 데이터베이스에 저장후 앞으로 이 데이터베이스에서 푸쉬메세지를 보내고자하는 디바이스 등록id를 찾아 메시지를 보내기 위함입니다.



등록 ID를 발급받은것만으로 푸쉬메시지를 보내고 받는것의 반은 한겁니다. 이제 푸쉬를 하는방법과 구글이 푸쉬한 메시지를 받는법에 대하여 설명드리겠습니다. 

푸쉬를 하기위해서는 이전 강의에서 받은 PROJECT ID와 simple api key와 등록 ID(위에서 설명한) 가 필요합니다. 이렇게해서 푸쉬메시지를 보내는 개발자를 알아내고 푸쉬메시지를 받는 디바이스를 알아내어 메시지가 전송되는겁니다. 푸쉬메시지를 수신하기위해서는 디바이스 내부에 몇가지 퍼미션과 서비스를 등록하여 구글에서 날라오는 메시지를 핸들만 해주면 손쉽게 메시지를 가져올 수 있습니다.



GCM의 구성원리는 이정도로 하고 이제 안드로이드 프로젝트 생성하고 서비스를 등록하여 GCM을 위한 등록ID 요청및 푸쉬메시지 핸들링에 대하여 보도록 하겠습니다.

GCM은 안드로이드 2.2버젼부터 사용가능한 것이므로 최소 api는 8로 설정하여 프로젝트를 생성해주세요. 그리고 1부 강좌에서 내려받은 GCM 라이브러리를 안드로이드 프로젝트에 libs 폴더내부에 복사해주세요. libs 폴더가 없는경우 생성해주시면 되겠습니다.

저의 경우는 gcm 라이브러리가 D:\dev\android_sdk\extras\google\gcm\gcm-client\dist 이 위치에 들어있습니다.

<위 사진은 2.3 api를 이용한것으로 2.2로 해도 상관없습니다.>

gcm.jar

<요청에 의해 라이브러리파일을 올려드립니다 ㅋ>

libs 폴더내부에 gcm.jar 라이브러리를 복사한후 라이브러리를 사용하겠다고 빌드패스에 등록합니다.



안드로이드 프로젝트에서 저는 시작부터 뷰를 구성하는 버릇이 있기때문에 일단 레이아웃부터 구성해봅시다. 레이아웃은 등록ID와 푸쉬된 메시지를 간단하게 표현하고 푸쉬 받기/받지않기 를 설정하는 체크박스 정도로 구성해보도록 하겠습니다. 

레이아웃은 어떤 모양이든 상관없습니다. 다만 서드파티를 사용하는 강의이므로 푸쉬받기/푸쉬받지않기 루틴에 대해 DB를 한번 조사하는 요청이 필요하지만 지금 강의에서는 그냥 체크에 따른 푸쉬 설정/해지만을 다루도록 하겠습니다. DB조사요청을 알고싶으시면 댓글을 달아주시면 루틴을 설명드리겠습니다.

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/LinearLayout1"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >



    <CheckBox

        android:id="@+id/checkBox1"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="푸쉬 받기 설정" />


    <TextView

        android:id="@+id/textView1"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="TextView" />

</LinearLayout>

레이아웃은 이정도가 되겠습니다.


이제 퍼미션과 리시버를 받기위해 AndroidManifest.xml 파일 설정을 해보도록 하겠습니다.

추가해야할 퍼미션은 

<uses-permission android:name="com.example.mygcm.permission.C2D_MESSAGE"/>

<permission android:name="com.example.mygcm.permission.C2D_MESSAGE" android:protectionLevel="signature" />

<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<uses-permission android:name="android.permission.WAKE_LOCK"/>

위 두 퍼미션은 안드로이드 4.1부터는 필요없다고 하네요. 그리고 퍼미션을 추가할때 패키지이름을 정확히 적어주셔야만 메시지를 핸들할수 있으니 실수없이 적으셔야합니다. 그다음 receiver와 service를 등록해야합니다.

추가할 xml 구문은

<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="com.example.mygcm" />

</intent-filter>

</receiver>

<service android:name=".GCMIntentService"></service>

intent-filter 내부에 category란에 패키지명을 정확히 적어주셔야 리시버가 제대로 동작됩니다.


AndroidManifest.xml 설정이 완료되었으면 이제 MainActivity 를 손봐줄차례입니다.

MainActivity 에서는 체크박스를 통해 푸쉬메시지를 받는지 받지않는지를 설정하는데 이것은 gcm.jar 라이브러리를 통해 구성합니다.

GCMRegister 라는 클래스 내부 스태틱 메소드들을 활용하여 GCM을 등록/해지하는데 다음 코드를 보면 금방 이해하실겁니다.

package com.example.mygcm;


import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.util.Log;

import android.view.Menu;

import android.widget.CheckBox;

import android.widget.CompoundButton;

import android.widget.CompoundButton.OnCheckedChangeListener;

import android.widget.TextView;


import com.google.android.gcm.GCMRegistrar;


public class MainActivity extends Activity {

public static Context mContext = null;

//푸쉬를 받기/받지 않기를 설정하기 위한 체크박스

public CheckBox cb_setting = null;

//푸쉬로 받은 메시지를 표현하기 위한 텍스트뷰

public static TextView tv_msg = null;


public static String PROJECT_ID = "2891710653";

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mContext = this;

        setContentView(R.layout.activity_main);

        tv_msg = (TextView)findViewById(R.id.textView1);

        cb_setting = (CheckBox)findViewById(R.id.checkBox1);

        cb_setting.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

// TODO Auto-generated method stub

//푸쉬 받기

if(isChecked){

Log.d("test","푸쉬 메시지를 받습니다.");

GCMRegistrar.checkDevice(mContext);

GCMRegistrar.checkManifest(mContext);

if(GCMRegistrar.getRegistrationId(mContext).equals("")){

GCMRegistrar.register(mContext, PROJECT_ID);

}else{

//이미 GCM 을 상요하기위해 등록ID를 구해왔음

GCMRegistrar.unregister(mContext);

GCMRegistrar.register(mContext, PROJECT_ID);

}

}

//푸쉬 받지않기

else{

Log.d("test","푸쉬 메시지를 받지 않습니다.");

GCMRegistrar.unregister(mContext);

}

}

});

        

    }


    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.activity_main, menu);

        return true;

    }

}


MainActivity 코딩이 완료되면 이제 직접적인 등록/해지/오류/메시지 핸들을 담당하는 서비스 클래스를 작성해야합니다.

아까 AndroidManifest.xml 에서 <service android:name=".GCMIntentService"></service>  부분에 GCMIntentService 라고 이름을 적었는데 이 이름과 동일한 클래스를 패키지 내부에 만들어주세요.


위 사진과 같이 4개의 메소드를 오버라이딩 해주시고 추가적으로 서비스가 잘 동작하는지에 대한 생성자를 구성해주세요. 메소드들은 모두 오버라이딩되어 사용되는데 이때 메소드 이름앞에 모두 on이 붙는 이유는 바로 이벤트가 발생할때 처리하려는 목적으로 만들어진 함수들이기 떄문입니다. 그래서 등록을 하거나 해지 또는 메시지를 수신받을때 모두 그에 해당되는 함수가 호출되어 저기서 처리가 가능하게끔하는것입니다. 

<브로드캐스터내부에서 뷰를 제어 할 수 없으므로 일단은 로그만 찍어보았습니다.>

아래 코드는 GCMIntentService 클래스의 코드입니다. 

package com.example.mygcm;


import android.content.Context;

import android.content.Intent;

import android.os.Handler;

import android.util.Log;

import android.widget.Toast;


import com.google.android.gcm.GCMBaseIntentService;


public class GCMIntentService extends GCMBaseIntentService{

//GCM에 정상적으로 등록되었을경우 발생하는 메소드

@Override

protected void onRegistered(Context arg0, String arg1) {

// TODO Auto-generated method stub

Log.d("test","등록ID:"+arg1);

}

//GCM에 해지하였을경우 발생하는 메소드

@Override

protected void onUnregistered(Context arg0, String arg1) {

Log.d("test","해지ID:"+arg1);

}

//GCM이 메시지를 보내왔을때 발생하는 메소드

@Override

protected void onMessage(Context arg0, Intent arg1) {

// TODO Auto-generated method stub

}

//오류를 핸들링하는 메소드

@Override

protected void onError(Context arg0, String arg1) {

Log.d("test",arg1); 

}

//서비스 생성자

public GCMIntentService() {

super(MainActivity.PROJECT_ID);

Log.d("test","GCM서비스 생성자 실행");

}

}


이것으로 2부 가이드를 마치겠습니다. 이번 강의에서는 GCM의 구성원리를 파악하는것에 중점을 두고 써내려갔는데 얼마나 이해될런지 모르겠습니다. 아직 안드로이드쪽의 개발이 완료된것은 아닙니다. 메시지 핸들링처리나 등록ID를 DB에 저장하는 요청도 하지 않았기때문인데, 다음 강의에서 등록ID를 DB에 누적하는 요청과 안드로이드가 어떻게 데이터베이스에 접근하는지에 대하여 강의하도록 하겠습니다.