Unity3D Android GCM Integration - 3. Send Single, Multi Push(without Server)

 유니티3D에 안드로이드 GCM 클라이언트 부분인 Sender ID 등록과 푸시 메세지 핸들링 후 알림 띄우기까지 정리해봤습니다. 이번에는 마지막으로 서버측 처리를 정리하겠습니다. 하지만 미리 언급했듯이 JSP나 PHP등의 서버가 아닌 안드로이드 자바딴에서 클라이언트 + 서버 기능을 사용하는 내용입니다.


1. GCM Server 라이브러리 준비


  안드로이드 Jar 프로젝트 빌드를 위해 gcm 서버 기능을 사용하기 위해 gcm-server.jar 파일을 자비 빌드 패스에 추가해줍니다. 위치는 스샷에 보이는 것과 같이 androidsdk/extras/google/gcm/gcm-server/dist 에 있습니다.

 당연히 유니티3D 최종 빌드를 위해 플러그인 디렉터리에도 복사를 해줍니다.

 마지막으로 androidsdk/extras/google/gcm/gcm-server/lib 에 있는 json_simple-1.1.jar파일을 유니티3D 플러그인 디렉터리에 복사해줍니다. 이것이 없다면 java.lang.NoClassDefFoundError: org.json.simple.JSONValue 오류가 발생합니다.


2. GCM에 단일 또는 멀티로 푸시하기

 원래는 자체 서버딴에서 처리해야할 푸시 기능을 안드로이드 프로젝트에 자바로 구현한 부분을 정리해보겠습니다. 아래는 기존 MainActivity에 추가 된 것입니다.

public class MainActivity extends UnityPlayerActivity {
private final String LOG_TAG = "UNITY_GCM_TEST";
private final String GCM_SENDER_ID = "xxxxxxxxxxxx";
// API ACCESS KEY
private final String API_KEY = "xxxxxxxxxxxxxxx";
// 이 앱을 실행중인 디바이스의 RegId
private String strRegId = null;
// 현 디바이스와 다른 디바이스 모두를 가지고 있는 RegId List
private List<String> regIdList = null;

// 메세지 전송 실패시 재시도 횟수

private final int MSG_SEND_RETRY = 3;
...
private class GCMPushTask extends AsyncTask<Message, Void, Void> {

@Override
protected Void doInBackground(Message... params) {
// TODO Auto-generated method stub
Sender gcmSender = new Sender(API_KEY);
try {
// 자신에게만 푸시 요청
if (regIdList == null) {
Result gcmResult = gcmSender.send(params[0], strRegId, MSG_SEND_RETRY);
if (gcmResult.getMessageId() != null) {
Log.d(LOG_TAG, "Push Success");
} else {
Log.d(LOG_TAG, "Push Failed " + gcmResult.getErrorCodeName());
}
} else {
// 등록된 다른 디바이스까지 요청
MulticastResult gcmMultiResult = gcmSender.send(params[0], regIdList, MSG_SEND_RETRY);
gcmMultiResult.getTotal();
gcmMultiResult.getSuccess();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public void PushMsg_U(final String strMsg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Message.Builder msgBuilder = new Message.Builder();
// 디바이스가 활성화 상태일 때 보여주려면 true
msgBuilder.delayWhileIdle(true);
// 디바이스 비활성화일 때 보관되는 시간.
msgBuilder.timeToLive(3);
msgBuilder.addData("Title", "Unity3DTestGCM");
msgBuilder.addData("Msg", strMsg);
GCMPushTask gcmPushTask = new GCMPushTask();
gcmPushTask.execute(msgBuilder.build());
}
});
}
public void AddOtherDevice_U() {
// TODO : 실제로는 서버에서 정보를 얻어오거나 서버에 있어야할 것들
if (this.regIdList == null) {
this.regIdList = new ArrayList<String>();
this.regIdList.add(this.strRegId);
this.regIdList.add("xxxxxxxxxxxxxxxxxxxxxxxxx");
}
}

 API_KEY 부분은 구글 API 콘솔 페이지에 있는 Api Access Key값을 기입해줍니다. 그런데 제가 처음 API Key생성 관련 정리할 때는 서버키를 생성했었는데 그냥 기존에 있는 Key for browser apps의 키를 사용해도 테스트가 되긴하네요. 최종 릴리즈때는 잘 모르겠지만요. 아무튼 서버에서 적용하신다면 서버키를 기입하시기 바랍니다.

  Message등은 android.os.Message 가 아니라 com.google.android.gcm.server.Sender 에 있는 Message입니다. import를 잘해줘야 충돌이 없습니다.

 GCM 푸시할 메세지 빌드는 runOnUiThread(new Runnable() { 에서 처리하고 실제 Sender를 통해서 send하는 네트워크와 관련된 처리는 AsyncTask<Message, Void, Void> { 사용해야합니다. 그렇지 않다면 android.os.NetworkOnMainThreadException 에러가 발생합니다.

 마지막에 List<String>에 add를 하는 스트링중 strRegId는 자신의 것이고 그 밑에 xxxxx쭉 있는것은 다른 디바이스에서 실행해서 로그로 확인한 RegID를 넣은 것입니다. 주석에도 있듯이 이 부분은 서버에서 처리되어야 할 부분이죠. 물론 앱에 모든 유저의 RegId값을 저런식으로 다 알고 있다면야 앱에서도 처리는 가능하겠습니다.

 아래는 유니티3D 내용입니다.

// GCMManager.cs
public class GCMManager : MonoBehaviour { ...
public string strGCMMsg = string.Empty;
...
public void PushMsg(string strMsg)
{
curActivity.Call("PushMsg_U", strMsg);
}
public void AddOtherDevice()
{
curActivity.Call("AddOtherDevice_U");
}
}
// TestGUI.cs
void OnGUI()
{
...
fYpos += 50;
GCMManager.GetInstance().strGCMMsg = GUI.TextField(new Rect(0, fYpos, 300, 50), GCMManager.GetInstance().strGCMMsg);
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Push Msg") == true)
{
GCMManager.GetInstance().PushMsg( GCMManager.GetInstance().strGCMMsg );
}
}
fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Add Device") == true)
{
GCMManager.GetInstance().AddOtherDevice();
}
 간단하게 푸시 메세지 버튼과 다른 디바이스의 정보를 추가하는 버튼, 푸시 메세지 내용을 입력할 텍스트 필드를 추가했습니다.
 A500 태블릿의 테스트 화면입니다. 한글도 잘네요. 알림을 클릭하면 앱 실행도 잘됩니다. 앱이 종료된 상태든 백그라운드에 실행되는 상태든 상관없이 잘됩니다.

  갤럭시S2에도 앱을 설치해서 RegId를 추출한 후 위에 설명한 소스와 같이 소스에 넣은후에 다시 빌드해서 A500 태블릿에만 새로운 버젼을 적용했습니다. 메세지를 보내기 전 스샷입니다.

 오른쪽이 A500이고 왼쪽이 갤럭시S2입니다. 멀티 푸시도 잘되네요.  자체 서버에서 DB와 연동같은 부분은 숙제로 남았네요. 하지만 이미 서버 개발자 이신분들은 위 소스를 참고해서 쉽게 개발할 수 있을 듯 싶네요.

댓글

이 블로그의 인기 게시물

'xxx.exe' 프로그램을 시작할 수 없습니다. 지정된 파일을 찾을 수 없습니다.

goorm IDE에서 node.js 프로젝트로 Hello World Simple Server 만들어 띄워보기

애드센스 수익을 웨스턴 유니온으로 수표대신 현금으로 지급 받아보자.