반응형

Implementing GCM Client on Android 안드로이드에 GCM 클라이언트 확장(Implementing)하기

A Google Cloud Messaging (GCM) Android client is a GCM-enabled app that runs on an Android device. To write your client code, we recommend that you use the GoogleCloudMessaging API.

구글 클라우드 메시징(GCM) 안드로이드 클라이언트는 안드로이드 디바이스에서 작동하는 GCM이 허용된 앱이다. 당신의 클라이언트 코드를 작성하기 위해서 우리는 구글 클라우드 메시징 API를 당신이 참고하는것을 추천한다.

Here are the requirements for running a GCM Android client: 아래는 안드로이드에서 GCM이 작동하기위한 요구 조건이다.

  • At a bare minimum, GCM requires devices running Android 2.2 or higher that also have the Google Play Store application installed, or an emulator running Android 2.2 with Google APIs. Note that you are not limited to deploying your Android applications through Google Play Store. 최소 조건으로 GCM은 안드로이드 2.2 이상을 필요로한다 또한, 구글 플레이스토어가 인스톨 외어있어야 하며, 에뮬레이터일경우도 안드로이드 구글API와함께 안드로이드 2.2가 필요하다. 그러나 구글 플레이스토어에서 배포될 필요는 없다.
  • However, if you want to continue to use new GCM features that are distributed through Google Play Services, the device must be running Android 2.3 or higher, or you can use an emulator running Android 2.3 with Google APIs. 그러나 당신이 계속해서 새로운 GCM의 구글 플레이스토어를 아우르는 서비스를 이용하고 싶다면, 디바이스는 안드로이드 2.3 이상에서 동작해야며 에뮬레이터를 쓸 경우도 안드로이드 2.3이상을 사용해야한다.
  • On Android devices, GCM uses an existing connection for Google services. For pre-3.0 devices, this requires users to set up their Google accounts on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher. 안드로이드 디바이스에서, GCM은 구글서비스와 이미 존재하는 연결(connection)을 사용한다. 안드로이드 3.0 이하의 디바이스에서는 유저가 구글 계정을 설정해야함 한다. 구글 어카운트는 안드로이드 4.0.4 이상의 버전에서는 필요로 하지 않는다.

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확장(implementation)을 위해서는 클라이언트와 서머 모두 확장(implementation)이 필요하다. implementing the server side에 대한 더많은 정보를 보려면 링크를 참조해라

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 코딩에 대해서 당신을 안내해 줄 것이다. 당신의 클라이언트 앱은 독단적으로 복잡할(arbitarily complex)수 도 있고, 최소한만을 충종할 수 도 있다, GCM 클라이언트는 반드시 등록(registrationID를 얻는 행위)코드를 포함해야하며, GCM이 전송한 메시지를 수신하기위한 브로드케스트 리스버를 가지고 있어야한다.

Step 1: Set Up Google Play Services 스텝1. 구글 플레이 서비스 설정(set up)


To write your client application, use the GoogleCloudMessaging API. 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.  당신의 클라이언트앱에서 구글클라우드 메시징 API를 사용하기 위해서, 당신은 구글 플레이 서비스SKD레 프로젝트 설정을 해야한다. Setup 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 .jarfile 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: 

주의: 당신이 플레이서비스 라디브러리에 당신의 프로젝트를 등록할때, 리소스가 함께 Setup Google Play Services SDK에서 설명한 대로 등록(add)되었는지 확인해라. 키포인트는 당신이 이클립스 프로젝트에서 간단하게 .jar 파일로 라이브러리를 참조하는것한방식으로는 동작하지 않는다는 것이다. 당신은 무조건 라이브러리를 참조하(referencing a libary)해야한다. 그게아니면 당신의 앱은 라이브러리에 접근할 수 없고, 앱은 재대로 동작하지 않을것디아. 만약 너가 안드로이드 스튜디오를 쓰고있다면 당신의 앱의 build.gradle 파일에 의존성(dependency)섹션에 아래에 있는 코드(string)을 추가하면 된다.

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

Step 2: Edit Your Application's Manifest 스텝2. 매니페스트 수정


Add the following to your application's 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.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 권한을 추가함으로써 앱이 슬립상태에서도 메시지를 수신하는 프로세서를 유지할 수 있다. 선택사항(Optional)이다. 앱이 슬립 상태에서도 디바이스에서 동작하기를 원할 경우에만 추가해라.
  • 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" 권한은 대른 앱이 등록허거나 메시지를 수신하는것은 예방해준다. 권한명(permission name)은 반드시 이 패턴과(패키지명.premissionC2D_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.permission.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.
  • com.google.android.c2dm.intent.RECEIVE, 수신기는 applicationPackage카테고리로 세팅되야한다. 리시버는 반드시 com.google.android.c2dm.permission.SEND 권한을 필요로한다. 그러면(so that) GCM프레임워크가 메시지를 앱으로 보낼 수 있다. 만일 너의 앱이 인텐트를 사용한다면(인텐트는 필수는 아니지만 흔한 패턴이다.) 이 리시버는 WakefulBroadcastReceiver의 한종류(instance of)가 될 것이다. WakefulBroadcastReceiver는 앱의 부분적 웨이크 락(partial wake lock)을 생성하거나 관리한다.
  • Service (typically an IntentService) to which the WakefulBroadcastReceiver passes off the work of handling the GCM message, while ensuring that the device does not go back to sleep in the process. Including anIntentService is optional—you could choose to process your messages in a regular BroadcastReceiver instead, but realistically, most apps will use a IntentService.
  • 서비스(일반적으로는 인텐트 서비스)가 GCM을 관리(handling)하기 위해서 WakefulBroadcastReceiver로 전달되는것은 디바이스가 슬립상태(sleep in process)로 돌아가지 않는것을 보장한다. 인텐트서비스를 포함하는것은 선택사항(optional)이다 - 당신은 메시지를 처리하기위해 일반적인(regular) BroadcastReceiver 를 선택할 수도 있다. 그러나 대부분의 앱은 인텐트 서비스를 사용할 것이다.
  • 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이 안드로이드 기능을 사용할 수 없는 특징을 가지고 있다면 매니페스트에 최소버전이 8(android:minSdkVersion="8") 또는 그 이상으로 되어있는지 확인해봐라. 이게 설정되어있으면 제대로 동작하지 않는 기기에는 인스톨되지 않는다. 

Here are excerpts from a sample manifest that supports GCM:  여기 GCM을 지원하는 매니패스트의 샘플을 발췌해 논것이있다:

<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 theGoogleCloudMessaging 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.

마침내 이제 코드를 쓴다. 이 섹션은 구글 클라우드 메시징API를 어떻게 사용하는지에 대한 간단한 클라이언트 앱 셈플이다. 샘플은 메인 액티비티(DemoActivity), 웨이크풀브로드케스트리시버(GcmBroadcastReceiver), 인텐트(GcmIntentService)로 구성되어있다. 당신은 이 코드의 완전한 코드를 오픈소스사이트(링크)에서 찾을 수 있다. 

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.
  • 다른것들 사이에, 셈플은 등록과 업스트림( 디바이스에서 클라우드로)메시지를 설명한다. 업스트림메시지는 CCS(XMPP)서버와 동작(running against)하는 앱만 지원한다; HTTP기반 서버는 업스트림 메시지를 서포트하지 않는다. 
  • 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.
  • 구글 클라우드 메시징 등록(registration) API는 예전 등록 프로세스(지금은 쓸수 없는 클라이언트 헬버 라이브러리 기반 프로세스)를 대체했다. 비록 예전 프로세스가 아직 작동하긴 하지만, 우리는 새로운 구글 클라우드 메시징 등록 API를 사용하기를 권고한다.

Check for Google Play Services APK 구글 플레이서비스 API 확인

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 inonResume() 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 SKD에 연걸되어있는 앱들은 항상구글플레이 스토어 서비스에 접속하기 전에 구글 플레이서비스APK에 호환이 되는지 확인해야한다.  예제(sample)앱에서 이 확인작업은 두곳에서 실행된다: onCreate메소드와 onResume메소드. onCreate메소드에서의 체크는 완전한 체크없이 앱을 사용할 수 없게한다. onResume메소드에서의 체크는 앱이 실행중 백번튼같은것을 눌렀을때 사용된다. 만약에 휴대폰이 구글 플레이서비스APK와 호환이 안된다면 당신의 앱은 GooglePlayServicesUtil.getErrorDialog()를 불러오게 되며 , 디바이스 시스템 세팅에서 구글플레이스토어APK를 다운로드받게 할것이다.

예를보자. 

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. //구글플레이서비스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. 여기에도 플레이서비스APK체크를 해야한다.
@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.

* 디바이스가 구글플레이스토어 APK를 가지고 있는지 확인한다.

* 만약에 APK가 없아면 다이얼로그를 통해서 유저가 APK를 다운받게한다.
 */

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에 등록

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서버에 등록되어있어야만한다. 앱이 등록될때, 앱은 미래에 사용될 registrationID를 받아온다(registrationID는 비밀로 유지되어야한다). 다음의 정보에 따르면 샘플 엡에 main actitivity의 onCreate() 는 GCM서머에 앱이 이미 등록되어있는지를 체크한다.

/**
 * Main UI for the demo app. //데모앱의 메인 UI
 */

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."

* 여기의 당신의 센더 아이디를 넣으세요. 센더아이디는 Getting Started에 성명되어있는 API콘솔에서 당신이 얻은 프로젝트 넘버입니다.
     */

   
String SENDER_ID = "Your-Sender-ID";

   
/**
     * Tag used on log messages. 로드메시지에 사용될 TAG
     */

   
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.

// 디바이스가 Play Services APK를 사용가능한지 체크한다. 체크가 성공하면 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:

앱은 shared preferences에 이미 저장된 regestrationid가 존재하는지 알아보기위해서 getRegistrationId()메소드를 호출한다. 

/**
 * Gets the current registration ID for application on GCM service. //현재 GCM서비스를 위해서 registrationId를 가져온다.
 * <p>
 * If result is empty, the app needs to register. //만약에 결과가 empty라면 앱은 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 registration ID is not guaranteed to work with
   
// the new app version.

//앱이 업데이트 되었는지 체크한다. 업데이트 되었다면 registrationID를 초기화해야만한다.

//새로운 버전의 앱에서는 이미 존재하는 registrationID가 작동한다는 보장이 없다.
   
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 registration ID in your app is up to you.

// 샘플앱은 shared preferences에 계속 registration id를 보관한다, 그러나 이부분은 당신이 원하는 방법으로 수정해도됟다.
   
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 registration ID. getRegistrationId() calls the following method to check the app version:

registrationID가 없거나 앱이 업데이트된경우 getregistrationID()메소드는 앱이 새로운 registrationId가 필요하단것을 알려주기 위해서 

 empty스트링을 리턴한다.  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:

만일 유효한 registrationID가 없다면, DemoActivity는 아래의 registrerInBackground()메소드를 호출하여 등록을한다.  GCM 메소드인 register()와 unregister()는 블로킹(트랜잭션이 처리될 때 락이 걸림)을한다. 그래서 이건 무조건 백그라운드 스레드에서 작업해야된다.샘플앱은 수행을 위해서 AsyncTask를 사용한다.

※아래의 구글 공식 방법으로는 작동을 안합니다. 제가 작성한 작동되는 버전을 곧 올리겠습니다.


/**
 * Registers the application with GCM servers asynchronously.//앱을 GCM서버에 비동기식으로 등록한다.
 * <p>
 * Stores the registration ID and app versionCode in the application's
 * shared preferences.

* 앱의 shared preferences에 registrationId와 버전코드를 저장한다.
 */

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, //http프로토콜을 이용해서 서버에 registrationID를 전송해야한다.
               
// so it can use GCM/HTTP or CCS to send messages to your app. //그것이 당신의 앱에 gcm/http 또는 ccs메시지를 사용가능하게 해준다.
               
// The request to your server should be authenticated if your app // 당신의 앱이 계정(account)를 사용한다면 서버에 요청할때 반드시 진짜임을 증명해야한다.
               
// 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.
//이 데모에서 우리는 우리는 전송할 필요가 없다. 왜냐하면 디바이스가 서버에 업스트림 메시지를 보낼것이고, 그것이 반사되어 메시지안에서 'from' 주소를 포함해주기때문이다.
               
// Persist the registration ID - no need to register again. /registrationid를 사용할때 다시 등록할 필요는 없다.
                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:  //한번 registrationID를 받으면 당신의 서버(서드파티서버)로 전송해라

/**
 * 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.
* registrationID를 HTTP프로토콜을 통해서 당신의 서버에 전송해라. 그것이 GCM/HTTP나 CCS메시지를 당신의 앱으로 전송할 수 있게 해준다.  
이 데모에서 우리는 우리는 전송할 필요가 없다. 왜냐하면 디바이스가 서버에 업스트림 메시지를 보낼것이고, 그것이 반사되어 메시지안에서 'from' 주소를 포함해주기때문이다.

 */
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 registration ID. You might choose to use a different approach in your app:

등록이 끝난 후, 앱은 미래에 사용하기 위해서 shared preferences에 registrationid를 저장하기 위해 storeRegistrationId()메소드를 호출한다.  이건 단지 registrationId를 저장하기 위한 한가지 방법일 뿐이다. 어떤방법을 쓰던 당신이 정해서 사용해라.

/**
 * Stores the registration ID and app versionCode in the application's //registrationID와 버전 코드를 저장한다.
 * {@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 before it can receive messages. A given registration ID is not guaranteed to last indefinitely, so the first thing your app should always do is check to make sure it has a valid registration ID (as shown in the code snippets above).

정해진 상태에 따르면, 안드로이드 앱은 메시지를 받기 전에 반드시 gcm서버에 등록을 해야하고 registrationID를 얻어야한다. 전달된 registrationID가 마지막 식별자라는것은 보장되지 않는다. 그래서 당신의 앱이 해야하는 첫번째 일은 registrationID가 유효한것인지 체크하는것이다. (snippets above에서 보여준 코드처럼)

In addition to confirming that it has a valid registration ID, 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 client apps from the device to make room for the new one.

추가적으로 유효안 registrationID인지 확인하기위해서, 앱은 등록의 TOO_MANY_REGISTRATIONS에러를 다룰 준비를 하고있어야한다. 이 에러는 디바이스가 GCM에 너무 많은 등록이 되어있다는것을 보여둔다. 이에러는 앱의 숫자가 극도로(extreme) 많을때만 나타난다. 처리방법은 새로은 registrationID를 위한 공간을 위해서 즉각적으로 다른 클라이언트앱의것들을 지우는 것이다.

Receive a downstream message  다운스트림 메시지 받기

As described above in Step 2, the app includes a WakefulBroadcastReceiver for thecom.google.android.c2dm.intent.RECEIVE intent. A broadcast receiver is the mechanism GCM uses to deliver messages.

Step2에 나온 셜명에 따르면, 앱은 com.google.android.c2dm.intent.RECEIVE를 위해서 WakefullBroadcastReceiver를 포함해야한다.  브로드캐스트 리시버는 GCM이 메시지를 전달하는 메카니즘이다.

WakefulBroadcastReceiver is a special type of broadcast receiver that takes care of creating and managing apartial wake lock for your app. It passes off the work of processing the GCM message to a Service (typically anIntentService), 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를 만들고, 다루는 특별한타입의 브로드캐스트 리시버이다. WakefulBroadcastReceiver는 서비스(일반적으로 인텐트서비스)를 처리하기위한 GCM메시지를 전달하고, 수행중에 sleep모드로 돌아가지않게 하는걸 보장한다. 만일 당신이 서비스하기위한 일을 전송중에 wake lock을 고정하지 않는다면 당신은 특별히 작업 수행전에 슬립모드로 들어가는것을 허용해야한다. 넷 결과는 앱이 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를 사용하는것이 필요하지않다. 만약 당신이 서비스를 필요로하지 않는 간단한 앱을 사용한다면, 당신은 GCM메시지를 일반적인 BroadcastReceiver로 가로챌수있고, 거기서 당신의 작업을 할 수 있다. 일단 GCM이 브로드캐스트리시버의 onReceive()메소드로 인텐트를 보내면 뭘하던 당신한테 달려있다.

This snippet starts GcmIntentService with the method startWakefulService(). This method is comparable tostartService(), 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:

이 정보는 GcmIntentService를 startWakefulSErvice()메소드와 함께 시작한다. 이 메소드는  WakefulBroadcastReceiver가 wake lock를 서비스가 시작할때 제어(holding)한다는 것을 제외하면 startService()메소드와 비슷하다  인텐트는 startWakefulService()와 함께 전달되어 추가의 wake lock 의 식별자를 홀드한다.

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
   
@Override
   
public void onReceive(Context context, Intent intent) {
       
// Explicitly specify that GcmIntentService will handle the intent. //GcmIntentService는 인텐트를 다룰수 있는것을 명확하게 명시한다.
       
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. ThecompleteWakefulIntent() method has as its parameter the same intent that was passed in from theWakefulBroadcastReceiver.

인텐트서비스는 실제 GCM메시지 다루기작업보다 아래에서 보여준다. 서비스가 끝나면, GcmBroadcastReceiver.completeWakefulIntent()를 호출해서 wake lock을 풀어준다. completeWakefulIntent()메소드는 WakefulBroadcastReceiver와 동일한 파라메터를 가지고있다.

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메시지가 어떤 작업을 수행할지는 당신에게 달려잇다 - 가능성은 끝이없다. 예를들어 메시지는 ping이나 새로운 컨텐츠를 앱에 알려주거나, 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. //getMessageType() 인텐트 파라미터는 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.
            *  메시지 타잎에 기초한 필터메시지. GCM이 미래에 확장할 수 있는 새로운 메지시타임과 같은것들은 당신이 다루려고 하거나, 인지할 수 없는 메시지일경우 전부 무시한다.

*/
           
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. 일반적 GCM메시지라면, 뭔일을 시켜라.
           
} 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. 이건 그냥 예제일뿐이도 gcm메시지로 뭘할지는 당신이 알아서해라
   
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());
   
}
}

Send an upstream message   업스트림 메시지 보내기

When the user clicks the app's Send button, the app sends an upstream message using the GoogleCloudMessagingAPI. 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.

유저가 앱의 센드 메시지를 보내면, 앱은 업스트림 메시지를 GoogleCloudMessgingAPI를 통해서 보낸다. 업스트림 메시지를 보내는거 대신에 당신의 서버는 반ㄴ드시 CCS랑 연결되어야한다. 당신은 샘플을 실행해보고 CCS에 접속해보기위해 Implementing an XMPP-based App 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("");
   
}
}

Running the Sample 샘플 실행하기


To run the sample: 

  1. Follow the instructions in Getting Started to get your sender ID and API key.
  2. 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.
  3. 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.

샘플 실행을 위해서:

1. GettingStartd의 설명을 따라서 당신의 senderId와 API키를 얻어라.
2. 문서에 나온거처럼 클라이언트엡에 
3.데모서버(자바 또는 파이선)에서의 작동은 XMPP에 기초한 앱서버를 확장하는것을 제공한다. 어떤 데모서버를 선택하던지, 서버가 작동하기전에 센더아이디와 API키를 수정하는것을 잊지말자.

Viewing Statistics


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

GCM앱에서 통계와 에러메시지를 보기위해서

  1. Go to the Developer Console.
  2. Login with your developer account.

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

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

    Now you are on the statistics page.

  4. Go to the drop-down menu and select the GCM metric you want to view.
1. 디벨로퍼콘솔로가라.
2.디벨로퍼 어카운트로 로그인해라. 너는 너의 앱 리스트를 볼 수 있을것이다.
3. 'statistics'항목을 클릭해라.
4. 드랍다운메뉴로가서 GCM metric을 선택해라.

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

구글API콘솔이 GCM에 허가되지 않은 상태라면, 디벨로커 콘솔을 이용해라.


반응형

+ Recent posts