본문 바로가기
기타 활동/영어공부

Google Cloud Messaging - Implementing GCM Client

by ★용호★ 2014. 12. 31.

※ 오역 주의

 

원문 : http://developer.android.com/google/gcm/client.html

Implementing GCM Client

GCM 클라이언트 구현하기


 

A Google Cloud Messaging (GCM) client is a GCM-enabled app that runs on an Android device. To write your client code, we recommend that you use the GCM APIs. The client helper library that was offered in previous versions of GCM still works, but it has been superseded by the more efficient GCM APIs.

Google Colud Messaging(GCM) 클라이언트는 안드로이드 기기에서 동작하는 GCM이 활성화된 앱이다. 클라이언트 코드를 작성하기 위해 GCM API들을 사용하는 것을 추천한다.  GCM의 지난 버젼에서 제공하는 클라이언트 도우미 라이브러리가 여전히 동작 중이지만 더 효율적인 GCM APIs에 의해 대체 되었다.


 

A full GCM implementation requires both a client implementation and a server implementation. For more information about implementing the server side, see Implementing GCM Server.

완전한 GCM 구현은 클라이언트와 서버 구현 모두 필요하다.  서버 사이드 구현에 대한 더 많은 정보를 원한다면 Implementing GCM Server를 참조해라.


 

The following sections walk you through the steps involved in writing a GCM client-side application. Your client app can be arbitrarily complex, but at bare minimum, a GCM client app must include code to register (and thereby get a registration ID), and a broadcast receiver to receive messages sent by GCM.

다음 절에서는 GCM 클라이언트 사이드 어플리케이션을 작성하는 단계에 대해 안내한다. 클라이언트 앱은 복잡할 수 있지만 최소한 register를 위한 코드와 GCM으로부터 보내진 메세지를 받기 위한 브로드캐스트 receiver를 포함되어야 한다.


 

Step 1: Set Up Google Play Services

1단계: Google Play Services 설치


 

To write your client application, use the GCM APIs. To use this API, you must set up your project to use the Google Play services SDK, as described in Setup Google Play Services SDK.

클라이언트 어플리케이션을 작성하기위해 GCM API들을 사용한다. 이 API를 사용하려면 Setup Google Play Services SDK에 설명되어 있는대로 Google Play services SDK를 사용하는 당신의 프로젝트에 설치해야 한다.


 

Caution: When you add the Play Services library to your project, be sure to add it with resources, as described in Setup Google Play Services SDK. The key point is that you must reference the library—simply adding a .jar file to your Eclipse project will not work. You must follow the directions for referencing a library, or your app won't be able to access the library's resources, and it won't run properly. If you're using Android Studio, this is the string to add to the dependency section of your application's build.gradle file:

프로젝트에 Play Services 라이브러리를 추가할 때 Setup Google Play Servies SDK에 설명된 대로 리소스들을 추가해야 한다. 중요한 점은 당신이 그 라이브러리를 참조해야한다는 것이다. - 단순히 eclipse 프로젝트로 .jar 파일을 추가하는 것으로는 동작하지 않을 것입니다. 라이브러리를 참조하기 위해 다음 지시사항을 따라야 한다. 라이브러리의 리소스를 액세스 할 수 없을 것이고 제대로 실행되지 않을 것이다. Android Studio를 사용중이라면 build.gradle파일의 dependency 부분에 이 문자열을 추가해야 한다.

dependencies {

 compile "com.google.android.gms:play-services:3.1.+"

}


 

Step 2: Edit Your Application's Manifest

2단계 : 어플리케이션의 Manifest 수정


 

Add the following to your application's manifest:

어플리케이션의 manifest에 다음 내용을 추가한다.

  • The com.google.android.c2dm.permission.RECEIVE permission so the Android application can register and receive messages.

안드로이드 어플리케이션의 com.google.android.c2dm.permission.RECEIVE 권한은 등록과 메시지 수신을 할 수 있다.

  • The android.permission.INTERNET permission so the Android application can send the registration ID to the 3rd party server.

안드로이드 어플리케이션의 android.permission.INTERNET 권한은 타사의 서버로 registration ID를 보낼 수 있다.

  • The android.permission.GET_ACCOUNTS permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)

GCM으로 android.permission.GET_ACCOUNTS 권한은 Goolge 계정을 요구한다. (기기가 Android 4.0.4 보다 낮은 버젼에서 동작하는 경우에만 필요하다.)

  • The android.permission.WAKE_LOCK permission so the application can keep the processor from sleeping when a message is received. Optional—use only if the app wants to keep the device from sleeping.

android.permission.WAKE_LOCK은 메시지를 수신할 때 프로세스가 sleeping 상태를 유지할 수 있다. 선택적으로 앱이 기기가 sleeping 상태를 유지하길 원하는 경우에 사용한다.

  • An applicationPackage + ".permission.C2D_MESSAGE" permission to prevent other Android applications from registering and receiving the Android application's messages. The permission name must exactly match this pattern—otherwise the Android application will not receive the messages.

applicationPackage + ".permission.C2D_MESSAGE" 권한은 이 안드로이드 어플리케이션 메시지들 등록, 수신하는 다른 안드로이드 어플리케이션을 방지한다.  

이 권한 이름은 이 패턴에 정확히 맞아야 한다. 그렇지 않으면 메시지를 수신받지 못할 것이다.

  • A receiver for com.google.android.c2dm.intent.RECEIVE, with the category set as applicationPackage. The receiver should require the com.google.android.c2dm.SEND permission, so that only the GCM Framework can send a message to it. If your app uses an IntentService (not required, but a common pattern), this receiver should be an instance of WakefulBroadcastReceiver. A WakefulBroadcastReceiver takes care of creating and managing a partial wake lock for your app.

applicationPackage로 설정 한 범주와 com.google.android.c2dm.intent.RECEIVE를 위한 receiver. 이 receiver는 com.google.android.c2dm.SEND 권한이 있어야한다. 그래서 오로지 GCM 프레임워크만이 메시지를 보낼 수 있다. 당신의 앱이 IntentService를 사용한다면 (불필요하지만 일반적인 패턴), 이 receiver는 WakefulBroadcastReceiver의 인스턴스를 사용해야 한다. WakefulBroadcastReceiver는 생성 및 앱에 대한 partial wake lock 관리를 처리한다.

서비스(일반적으로 IntentService)의 하나인 WakefulBroadcastReceiver는 기기가 그 과정에서 sleep으로 돌아오지 않는 것을 보장하는 동안 GCM 메시지를 처리하는 일을 수행한다. IntentService를 포함하는 것은 선택적이다. 대신 일반 BroadcastReceiver에 당신의 메시지를 처리하도록 선택할 수 있지만 현실적으로 대부분의 어플리케이션은 IntentService를 사용한다.

  • If the GCM feature is critical to the Android application's function, be sure to set android:minSdkVersion="8" or higher in the manifest. This ensures that the Android application cannot be installed in an environment in which it could not run properly.

GCM 기능이 안드로이드 어플리케이션의 중요한 기능이라면 android:minSdkVersion="8" 또는 manifest에 더 높은 값으로 설정해야한다.  이는 안드로이드 어플리케이션이 정확하게 동작할 수 없는 환경에서 설치될 수 없는 것을 보장한다.


 

Here are excerpts from a sample manifest that supports GCM:

다음은 GCM이 지원하는 샘플 manifest로부터 발췌했다:

<manifest package="com.example.gcm" ...>


 

   <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/>

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

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

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

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


 

   <permission android:name="com.example.gcm.permission.C2D_MESSAGE"

       android:protectionLevel="signature" />

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


 

   <application ...>

       <receiver

           android:name=".GcmBroadcastReceiver"

           android:permission="com.google.android.c2dm.permission.SEND" >

           <intent-filter>

               <action android:name="com.google.android.c2dm.intent.RECEIVE" />

               <category android:name="com.example.gcm" />

           </intent-filter>

       </receiver>

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

   </application>


 

</manifest>

Step 3: Write Your Application

3단계: 어플리케이션 제작


 

Finally, write your application. This section features a sample client application that illustrates how to use the GoogleCloudMessaging API. The sample consists of a main activity (DemoActivity), a WakefulBroadcastReceiver (GcmBroadcastReceiver), and an IntentService (GcmIntentService). You can find the complete source code for this sample at the open source site.

마침내 어플리케이션 제작에 들어간다. 이 절의 기능들은 GoogleCloudMessaging을 어떻게 사용하는지를 보여주는 sample client application 이다.  이 sample은 main activity(DemoActivity), WakefulBroadcastReceiver(GcmBroadcastReceiver) 그리고 IntentService(GcmIntentService)로 구성되어 있다. open source site에 이 샘플의 완성된 소스 코드가 있다.


 

Note the following:

다음을 기억해라:

  • Among other things, the sample illustrates registration and upstream (device-to-cloud) messaging. Upstream messaging only applies to apps that are running against a CCS (XMPP) server; HTTP-based servers don't support upstream messaging.

무엇보다 이 샘플이 보여주는 registration과 upstream(device-to-cloud) messaging을 기억해라. Upstream messaging은 오로지 CCS(XMPP) 서버에서 동작하는 앱들에만 적용된다. HTTP 기반의 서버들은 upstream messaging이 지원되지 않는다.

  • The GoogleCloudMessaging registration APIs replace the old registration process, which was based on the now-obsolete client helper library. While the old registration process still works, we encourage you to use the newer GoogleCloudMessaging registration APIs, regardless of your underlying server.

GoogleColudMessaging registration APIs는 지금은 사용되지 않는 client helper library에 기반하는  기존 registration process를 교체한다. 기존 registration process가 여전히 수행되면 기반 서버에 관계없이 새로운 GoogleCloudMessaging regstration APIs를 사용하길 권장한다.


 

Check for Google Play Services APK

Google Play Services APK의 검사

As described in Setup Google Play Services SDK, apps that rely on the Play Services SDK should always check the device for a compatible Google Play services APK before accessing Google Play services features. In the sample app this check is done in two places: in the main activity's onCreate() method, and in its onResume() method. The check in onCreate() ensures that the app can't be used without a successful check. The check in onResume() ensures that if the user returns to the running app through some other means, such as through the back button, the check is still performed. If the device doesn't have a compatible Google Play services APK, your app can call GooglePlayServicesUtil.getErrorDialog() to allow users to download the APK from the Google Play Store or enable it in the device's system settings. For example:

Setup Google Play Services SDK에 설명되어 있는 Play Services SDK에 의존적인 앱들은 Google Play services들의 기능에 액세스하기 전에 Google Play services APK가 기기와 호환 되는지 항상 검사 해야한다. 샘플 앱에서는 두가지 검사를 했었다. main activity의 onCreate() 메소드와 onResume() 메소드에서 검사를 했다. onCreate()에서의 검사는 앱이 성공적인 검사 없이는 사용될 수 없음을 보장한다. onResume() 에서의 검사는 사용자가 back 버튼과 같은 어떤 다른 동작에 의해 수행중인 앱으로 return 되었을 때 여전히  수행 될 것을 보장한다. 기기가 호환되는 Google Play services APK가 없을 경우 Google Play Store에서 APK를 다운받기를 허용하거나 기기의 시스템 설정에서 이를 활성화 시킨 유저들은 GooglePlayServicesUtil.getErrorDialog()를 호출할 수 있다.

예:

private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

...

@Override

public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);


 

   setContentView(R.layout.main);

   mDisplay = (TextView) findViewById(R.id.display);


 

   context = getApplicationContext();


 

   // Check device for Play Services APK.

   if (checkPlayServices()) {

       // If this check succeeds, proceed with normal processing.

       // Otherwise, prompt user to get valid Play Services APK.

       ...

   }

}


 

// You need to do the Play Services APK check here too.

@Override

protected void onResume() {

   super.onResume();

   checkPlayServices();

}


 

/**

* Check the device to make sure it has the Google Play Services APK. If

* it doesn't, display a dialog that allows users to download the APK from

* the Google Play Store or enable it in the device's system settings.

*/

private boolean checkPlayServices() {

   int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

   if (resultCode != ConnectionResult.SUCCESS) {

       if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {

           GooglePlayServicesUtil.getErrorDialog(resultCode, this,

                   PLAY_SERVICES_RESOLUTION_REQUEST).show();

       } else {

           Log.i(TAG, "This device is not supported.");

           finish();

       }

       return false;

   }

   return true;

}

Register for GCM

GCM을 위한 Register

An Android application needs to register with GCM servers before it can receive messages. When an app registers, it receives a registration ID, which it can then store for future use (note that registration IDs must be kept secret). In the following snippet the onCreate() method in the sample app's main activity checks to see if the app is already registered with GCM and with the server:

안드로이드 어플리케이션은 메시지를 수신받기 전에 GCM server들과 함께 register가 필요하다. app register들이 registration ID를 받으면 나중에 사용할 것을 위해 저장할 수 있다. (registration ID들은 반드시 보안 유지에 주의해야 한다.) 다음으로 샘플 앱의 main activity에서 onCreate() 메서드는 앱이 이미 GCM과 서버들에 등록되어 있는지를 검사한다.  


 

/**

* Main UI for the demo app.

*/

public class DemoActivity extends Activity {


 

   public static final String EXTRA_MESSAGE = "message";

   public static final String PROPERTY_REG_ID = "registration_id";

   private static final String PROPERTY_APP_VERSION = "appVersion";

   private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;


 

   /**

    * Substitute you own sender ID here. This is the project number you got

    * from the API Console, as described in "Getting Started."

    */

   String SENDER_ID = "Your-Sender-ID";


 

   /**

    * Tag used on log messages.

    */

   static final String TAG = "GCMDemo";


 

   TextView mDisplay;

   GoogleCloudMessaging gcm;

   AtomicInteger msgId = new AtomicInteger();

   SharedPreferences prefs;

   Context context;


 

   String regid;


 

   @Override

   public void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);


 

       setContentView(R.layout.main);

       mDisplay = (TextView) findViewById(R.id.display);


 

       context = getApplicationContext();


 

       // Check device for Play Services APK. If check succeeds, proceed with

       //  GCM registration.

       if (checkPlayServices()) {

           gcm = GoogleCloudMessaging.getInstance(this);

           regid = getRegistrationId(context);


 

           if (regid.isEmpty()) {

               registerInBackground();

           }

       } else {

           Log.i(TAG, "No valid Google Play Services APK found.");

       }

   }

...

}

The app calls getRegistrationId() to see whether there is an existing registration ID stored in shared preferences:

앱은 getRegistrationId()을 호출하여 shared preferences에 registration ID가 존재하는지 여부를 확인한다.


 

/**

* Gets the current registration ID for application on GCM service.

* <p>

* If result is empty, the app needs to register.

*

* @return registration ID, or empty string if there is no existing

*         registration ID.

*/

private String getRegistrationId(Context context) {

   final SharedPreferences prefs = getGCMPreferences(context);

   String registrationId = prefs.getString(PROPERTY_REG_ID, "");

   if (registrationId.isEmpty()) {

       Log.i(TAG, "Registration not found.");

       return "";

   }

   // Check if app was updated; if so, it must clear the registration ID

   // since the existing regID is not guaranteed to work with the new

   // app version.

   int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);

   int currentVersion = getAppVersion(context);

   if (registeredVersion != currentVersion) {

       Log.i(TAG, "App version changed.");

       return "";

   }

   return registrationId;

}

...

/**

* @return Application's {@code SharedPreferences}.

*/

private SharedPreferences getGCMPreferences(Context context) {

   // This sample app persists the registration ID in shared preferences, but

   // how you store the regID in your app is up to you.

   return getSharedPreferences(DemoActivity.class.getSimpleName(),

           Context.MODE_PRIVATE);

}



 

If the registration ID doesn't exist or the app was updated, getRegistrationId() returns an empty string to indicate that the app needs to get a new regID. getRegistrationId() calls the following method to check the app version:

registration ID가 존재하지 않거나 앱이 업데이트 된 경우 getRegistationId()는 새로운 regID를 얻어야한다는 표시를 위해 빈 문자열을 반환한다.  getRegistrationId()는 앱 버젼을 체크하기 위해 다음 메서드를 호출한다.


 

/**

* @return Application's version code from the {@code PackageManager}.

*/

private static int getAppVersion(Context context) {

   try {

       PackageInfo packageInfo = context.getPackageManager()

               .getPackageInfo(context.getPackageName(), 0);

       return packageInfo.versionCode;

   } catch (NameNotFoundException e) {

       // should never happen

       throw new RuntimeException("Could not get package name: " + e);

   }

}


 

If there isn't a valid existing registration ID, DemoActivity calls the following registerInBackground() method to register. Note that because the GCM methods register() and unregister() are blocking, this has to take place on a background thread. This sample uses AsyncTask to accomplish this:

가지고 있는 registration ID가 유효하지 않다면 DemoActivity는 등록을 위해 다음 registerInBackground() 메서드를 호출한다. GCM 메서드인 register()와 unregister()가 blocking되어 백그라운드 스레드에서 동작하기  때문에 주의해야 한다.  이 샘플은 이를 위해 AsyncTask를 사용한다.


 

/**

* Registers the application with GCM servers asynchronously.

* <p>

* Stores the registration ID and app versionCode in the application's

* shared preferences.

*/

private void registerInBackground() {

   new AsyncTask() {

       @Override

       protected String doInBackground(Void... params) {

           String msg = "";

           try {

               if (gcm == null) {

                   gcm = GoogleCloudMessaging.getInstance(context);

               }

               regid = gcm.register(SENDER_ID);

               msg = "Device registered, registration ID=" + regid;


 

               // You should send the registration ID to your server over HTTP,

               // so it can use GCM/HTTP or CCS to send messages to your app.

               // The request to your server should be authenticated if your app

               // is using accounts.

               sendRegistrationIdToBackend();


 

               // For this demo: we don't need to send it because the device

               // will send upstream messages to a server that echo back the

               // message using the 'from' address in the message.


 

               // Persist the regID - no need to register again.

               storeRegistrationId(context, regid);

           } catch (IOException ex) {

               msg = "Error :" + ex.getMessage();

               // If there is an error, don't just keep trying to register.

               // Require the user to click a button again, or perform

               // exponential back-off.

           }

           return msg;

       }


 

       @Override

       protected void onPostExecute(String msg) {

           mDisplay.append(msg + "\n");

       }

   }.execute(null, null, null);

   ...

}

Once you've received your registration ID, send it to your server:

수신 받은 registration ID를 서버로 전송한다.


 

/**

* Sends the registration ID to your server over HTTP, so it can use GCM/HTTP

* or CCS to send messages to your app. Not needed for this demo since the

* device sends upstream messages to a server that echoes back the message

* using the 'from' address in the message.

*/

private void sendRegistrationIdToBackend() {

   // Your implementation here.

}


 

After registering, the app calls storeRegistrationId() to store the registration ID in shared preferences for future use. This is just one way of persisting a regID. You might choose to use a different approach in your app:

등록을 마친 후 앱은 나중에 사용하기 위해 shared preferences에 registration을 저장하려고 storeRegistrationId()를 호출한다. 이는 regID를 지속하는 방법 중 하나이다.  당신은 앱에서 다른 방식을 사용하도록 선택할 수 있다.


 

/**

* Stores the registration ID and app versionCode in the application's

* {@code SharedPreferences}.

*

* @param context application's context.

* @param regId registration ID

*/

private void storeRegistrationId(Context context, String regId) {

   final SharedPreferences prefs = getGCMPreferences(context);

   int appVersion = getAppVersion(context);

   Log.i(TAG, "Saving regId on app version " + appVersion);

   SharedPreferences.Editor editor = prefs.edit();

   editor.putString(PROPERTY_REG_ID, regId);

   editor.putInt(PROPERTY_APP_VERSION, appVersion);

   editor.commit();

}


 

Handle registration errors

registration 처리 오류들


 

As stated above, an Android app must register with GCM servers and get a registration ID (regID) before it can receive messages. A given regID is not guaranteed to last indefinitely, so the first thing your app should always do is check to make sure it has a valid regID (as shown in the code snippets above).

안드로이드 앱은 message를 수신받을 수 있게 되기 전에 GCM 서버로 등록하고 registrationID를 발급 받아야 한다. 주어진 regID는 무기한 지속 보장을 할 수 없다. 그래서 첫번째로 당신의 앱은 regID가 유효한지를  항상 검사 해야 한다. (위의 코드에서 미리 봤었다.)


 

In addition to confirming that it has a valid regID, your app should be prepared to handle the registration error TOO_MANY_REGISTRATIONS. This error indicates that the device has too many apps registered with GCM. The error only occurs in cases where there are extreme numbers of apps, so it should not affect the average user. The remedy is to prompt the user to delete some of the other GCM-enabled apps from the device to make room for the new one.

regiID가 유효한지 확인을 하는 것 외에도 registration error인 TOO_MANY_REGISTRATIONS를 처리할 준비를 해야 한다. 이 에러는 GCM에 너무 많은 앱들을 등록한 기기에 표시된다. 이 에러는 앱의 수가 극도로 많을 경우에만 발생한다. 그래서 일반 유저들은 영향이 없다. 해결방법은 새로운 공간을 만들기 위해 기기에 GCM이 활성화된 다른 앱들을 제거할 것을 사용자에게 표시하는 것이다.


 

Send a message

메세지 전송


 

When the user clicks the app's Send button, the app sends an upstream message using the GoogleCloudMessaging API. In order to receive the upstream message, your server should be connected to CCS. You can use one of the demo servers in Implementing an XMPP-based App Server to run the sample and connect to CCS.

사용자가 앱의 Send 버튼을 클랙했을 때 앱은 GoogleCloudMessaging API를 사용하여 upstream message를 전송한다.  upstream message를 수신받기 위해서 당신의 서버는 CCS에 연결되어야 한다. 샘플을 수행하고 CCS에 연결하기 위해 Implementing an XMPP-based App Server에 있는 demo server들 중 하나를 사용할 수 있다.  


 

public void onClick(final View view) {

   if (view == findViewById(R.id.send)) {

       new AsyncTask() {

           @Override

           protected String doInBackground(Void... params) {

               String msg = "";

               try {

                   Bundle data = new Bundle();

                       data.putString("my_message", "Hello World");

                       data.putString("my_action",

                               "com.google.android.gcm.demo.app.ECHO_NOW");

                       String id = Integer.toString(msgId.incrementAndGet());

                       gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data);

                       msg = "Sent message";

               } catch (IOException ex) {

                   msg = "Error :" + ex.getMessage();

               }

               return msg;

           }


 

           @Override

           protected void onPostExecute(String msg) {

               mDisplay.append(msg + "\n");

           }

       }.execute(null, null, null);

   } else if (view == findViewById(R.id.clear)) {

       mDisplay.setText("");

   }

}



Receive a message

메시지 수신

As described above in Step 2, the app includes a WakefulBroadcastReceiver for the com.google.android.c2dm.intent.RECEIVE intent. A broadcast receiver is the mechanism GCM uses to deliver messages. When onClick() calls gcm.send(), it triggers the broadcast receiver's onReceive() method, which has the responsibility of making sure that the GCM message gets handled.

위의 Step2에서 설명하였듯이 이 앱은 com.google.android.c2dm.intent.RECEIVE 를 위해 WakefulBroadcastReceiver를 포함해야 한다. broadcast receiver는 메시지 제공을 위해 GCM 메커니즘을 사용해야 한다. onClick()함수가 gcm.send()를 호출 할 때, GCM 메시지 처리를 확인 할 책임을 지는 broadcast receiver의 onReceive()메소드가 트리거 된다.


A WakefulBroadcastReceiver is a special type of broadcast receiver that takes care of creating and managing a partial wake lock for your app. It passes off the work of processing the GCM message to a Service (typically an IntentService), while ensuring that the device does not go back to sleep in the transition. If you don't hold a wake lock while transitioning the work to a service, you are effectively allowing the device to go back to sleep before the work completes. The net result is that the app might not finish processing the GCM message until some arbitrary point in the future, which is not what you want.

WakefulBroadcastReceiver는 당신의 앱을 위해 partial wake lock의 생성과 관리를 처리하는 broadcast receiver의 특별한 타입이다. 이는 기기가 sleep 상태로 돌아가지 않게 보장하는 동안 Service(일반적으로 IntentService)로 GCM 메시지 처리 작업을 넘긴다. service를 위한 작업이 전환되는 동안 wake lock을 걸지 않는 다면 작업이 완료되기 전에 기기가 sleep 상태로 돌아가는 것을 허용할 수 밖에 없을 것이다. 최종 결과로 원치 않게 미래의 어떤 임의 포인트까지 GCM 메시지가 처리되는 것을 완료하지 못할 것이다.


Note: Using WakefulBroadcastReceiver is not a requirement. If you have a relatively simple app that doesn't require a service, you can intercept the GCM message in a regular BroadcastReceiver and do your processing there. Once you get the intent that GCM passes into your broadcast receiver's onReceive() method, what you do with it is up to you.

주의 : WakefulBroadcastReceiver를 사용하는 것은 요구사항이 아니다. service를 필요로 하지  않는 상대적으로 간단한 앱일 경우에 정기적인 BroadcastReceiver로 GCM 메시지를 차단하고 거기에 처리를 할 수 있다.

This snippet starts GcmIntentService with the method startWakefulService(). This method is comparable to startService(), except that the WakefulBroadcastReceiver is holding a wake lock when the service starts. The intent that is passed with startWakefulService() holds an extra identifying the wake lock:

이 절에서는 startWakefulService() 메서드로 GcmIntentService를 시작한다. 이 메서드는 WakefulBroadcastReceiver가 service 시작시에 wake lock을 걸고 하는 것이 startService()와 유사하다. 이 intent는 wake lock의 여분을 보유하는(?) startWakefulService()으로 전달한다.


public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

   @Override

   public void onReceive(Context context, Intent intent) {

       // Explicitly specify that GcmIntentService will handle the intent.

       ComponentName comp = new ComponentName(context.getPackageName(),

               GcmIntentService.class.getName());

       // Start the service, keeping the device awake while it is launching.

       startWakefulService(context, (intent.setComponent(comp)));

       setResultCode(Activity.RESULT_OK);

   }

}


The intent service shown below does the actual work of handling the GCM message. When the service is finished, it calls GcmBroadcastReceiver.completeWakefulIntent() to release the wake lock. The completeWakefulIntent() method has as its parameter the same intent that was passed in from the WakefulBroadcastReceiver.

아래에서 intent service의 GCM 메시지 처리의 실 작업을 보여준다. 서비스가 종료되었을 때, wake lock을 해제하는 GcmBroadcastReceiver.completeWakefulIntent()를 호출한다. completeWakefulIntent() 메서드는 WakefulBroadcastReceiver와 같은 intent 파라미터를 갖는다.


This snippet processes the GCM message based on message type, and posts the result in a notification. But what you do with GCM messages in your app is up to you—the possibilities are endless. For example, the message might be a ping, telling the app to sync to a server to retrieve new content, or it might be a chat message that you display in the UI.

이 단편은 GCM 메시지 기반으로 처리하고 그 결과를 알린다. 앱에서 GCM 메시지와 함께 한다는 것은 당신에게 달려 있다. 무한한 가능성이 있다. 예를 들면 새로운 컨텐트를 검색하려고 서버에 동기화할 앱과 대화를 하고 핑 될 수 있다. 또는 UI에 채팅 메시지가 출력될 수 있다.


public class GcmIntentService extends IntentService {

   public static final int NOTIFICATION_ID = 1;

   private NotificationManager mNotificationManager;

   NotificationCompat.Builder builder;


   public GcmIntentService() {

       super("GcmIntentService");

   }


   @Override

   protected void onHandleIntent(Intent intent) {

       Bundle extras = intent.getExtras();

       GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

       // The getMessageType() intent parameter must be the intent you received

       // in your BroadcastReceiver.

       String messageType = gcm.getMessageType(intent);


       if (!extras.isEmpty()) {  // has effect of unparcelling Bundle

           /*

            * Filter messages based on message type. Since it is likely that GCM

            * will be extended in the future with new message types, just ignore

            * any message types you're not interested in, or that you don't

            * recognize.

            */

           if (GoogleCloudMessaging.

                   MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {

               sendNotification("Send error: " + extras.toString());

           } else if (GoogleCloudMessaging.

                   MESSAGE_TYPE_DELETED.equals(messageType)) {

               sendNotification("Deleted messages on server: " +

                       extras.toString());

           // If it's a regular GCM message, do some work.

           } else if (GoogleCloudMessaging.

                   MESSAGE_TYPE_MESSAGE.equals(messageType)) {

               // This loop represents the service doing some work.

               for (int i=0; i<5; i++) {

                   Log.i(TAG, "Working... " + (i+1)

                           + "/5 @ " + SystemClock.elapsedRealtime());

                   try {

                       Thread.sleep(5000);

                   } catch (InterruptedException e) {

                   }

               }

               Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());

               // Post notification of received message.

               sendNotification("Received: " + extras.toString());

               Log.i(TAG, "Received: " + extras.toString());

           }

       }

       // Release the wake lock provided by the WakefulBroadcastReceiver.

       GcmBroadcastReceiver.completeWakefulIntent(intent);

   }


   // Put the message into a notification and post it.

   // This is just one simple example of what you might choose to do with

   // a GCM message.

   private void sendNotification(String msg) {

       mNotificationManager = (NotificationManager)

               this.getSystemService(Context.NOTIFICATION_SERVICE);


       PendingIntent contentIntent = PendingIntent.getActivity(this, 0,

               new Intent(this, DemoActivity.class), 0);


       NotificationCompat.Builder mBuilder =

               new NotificationCompat.Builder(this)

       .setSmallIcon(R.drawable.ic_stat_gcm)

       .setContentTitle("GCM Notification")

       .setStyle(new NotificationCompat.BigTextStyle()

       .bigText(msg))

       .setContentText(msg);


       mBuilder.setContentIntent(contentIntent);

       mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

   }

}


Running the Sample

샘플 실행


To run the sample:

샘플을 실행하려면:

  1. Follow the instructions in Getting Started to get your sender ID and API key.

sender ID와 API 키를 얻기 위해 Getting Started 에서의 명령들을 수행해라.

  1. Implement your client app, as described in this document. You can find the complete source code for the client app at the open source site.

이 문서에 설명된 대로 클라이언트 앱을 구현해라. open source site에서 클라이언트 앱을 위한 완성된 소스 코드를 찾을 수 있을 것이다.

  1. Run one of the demo servers (Java or Python) provided in Implementing an XMPP-based App Server. Whichever demo server you choose, don't forget to edit its code before running it to supply your sender ID and API key.

Implementing an XMPP-based App Server 에서 제공되는 데모 서버들(Java 또는 Python) 중 하나를 수행해라. 어떤 데모 서버를 선택하든 sender ID와 API key 공급받기 위한 작업을 수행하기 전에 코드를 수정하는 것을 잊지 말아라.

Viewing Statistics

통계 확인


To view statistics and any error messages for your GCM applications:

GCM 어플리케이션을 위한 통계와 error 메시지를 보려면:

  1. Go to the Developer Console.

Developer Console을 방문해라.

  1. Login with your developer account.

당신의 developer 계정으로 로그인해라.

  1. You will see a page that has a list of all of your apps.

당신은 앱들의 모든 리스트를 가진 페이지를 보게될 것이다.

  1. Click on the "statistics" link next to the app for which you want to view GCM stats.

당신이 원하는 GCM 상태를 보기 위해 statistics 를 클릭하여 다음 링크로 넘어가라.

  1. Now you are on the statistics page.

statistic 페이지에 위치해 있을 것이다.

  1. Go to the drop-down menu and select the GCM metric you want to view.

드롭다운 메뉴로 가서 당신이 원하는 GCM metric을 선택해라.

Note: Stats on the Google API Console are not enabled for GCM. You must use the Developer Console.

주의 : Google API Console 통계는 GCM을 사용할 수 없도록 비활성화 되어있다. 당신은 Developer Console을 사용해야만 한다.


댓글