GCM – новый сервис Push-уведомлений от Google

image
Ранее в Android использовался C2DM (Cloud to Device Messaging), как сервис доставки Push-уведомлений на устройство. Но 26 июня он был официально отменен гуглом. На его место пришел новый GCM (Google Cloud Messaging).

Похожие названия. Одинаковая роль. В чем же разница ?

  • Для использования GCM, необходимо получить Simple API Key в консоли Google APIs.
  • Для GCM нужно получить Sender ID. Он является эквивалентом электронной почты в C2DM. Получить его можно опять-таки из консоли Google APIs, а точнее из URL:
    code.google.com/apis/console/#project:{SENDER_ID}
  • Уведомления в GCM имеют формат JSON вместе с простым текстом.
  • GCM может отправлять уведомления сразу на несколько устройств.
  • Теперь одно устройство с одним идентификатором регистрации может получать уведомления сразу с нескольких серверов.
  • Теперь уведомления могут иметь время жизни до 4-х недель. GCM будет хранить их до истечения срока.
  • Теперь можно отправлять уведомления до 4Кб с полезной нагрузкой. Это будет очень выгодно для реал-тайма различных чатов. Однако данный метод будет сильней кушать батарейку устройства.
  • Теперь нет необходимости передавать идентификатор устройства на сервер, чтобы избежать повторных регистраций одного устройства. Канонический идентификатор регистрации определяется GCM по последней регистрации устройства. И если сервер отправит уведомление со старым идентификатором, то GCM вернет канонический (последний) идентификатор, на который надо будет заменить старый.


Настройка GCM


Начнем с Android Manifest


Сначала нужно прописать разрешения:
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission android:name="{package}.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="{package}.permission.C2D_MESSAGE" /> 
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 


Затем ресивер и сервис:
		
<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="{package}" />
			</intent-filter>
		</receiver>
		
		<service android:name=".GCMIntentService" />


* {package} заменить на ваш пакет (у меня com.habrahabr.gcm)

Затем в корневом каталоге пакета создаем класс GCMIntentService, наследуемый от GCMBaseIntentService:

package {package};

import android.app.Activity;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {
	
    private static final String TAG = "GCMIntentService";

    public GCMIntentService() {
        super(GCMConfig.SENDER_ID);
    }

    @Override
    protected void onRegistered(Context context, String registrationId) {
        Log.i(TAG, "Device registered");
        // Здесь мы должны отправить registrationId на наш сервер, чтобы он смог на него отправлять уведомления
    }

    @Override
    protected void onUnregistered(Context context, String registrationId) {
        Log.i(TAG, "Device unregistered");
        
    }

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.i(TAG, "Received new message");
    }

    @Override
    protected void onDeletedMessages(Context context, int total) {
        Log.i(TAG, "Received deleted messages notification");
    }

    @Override
    public void onError(Context context, String errorId) {
        Log.i(TAG, "Received error: " + errorId);
    }

    @Override
    protected boolean onRecoverableError(Context context, String errorId) {
        Log.i(TAG, "Received recoverable error: " + errorId);
        return super.onRecoverableError(context, errorId);
    }
}


И уже после этого в главном активити прописываем:

        // Делаем проверки
        GCMRegistrar.checkDevice(this);
        GCMRegistrar.checkManifest(this);
        
        // Достаем идентификатор регистрации
        final String regId = GCMRegistrar.getRegistrationId(this);
        
        if (regId.equals("")) { // Если отсутствует, то регистрируемся
          GCMRegistrar.register(this, GCMConfig.SENDER_ID);
        } else {
          Log.v("GCM", "Already registered: " + regId);
        }


Теперь все готово, за исключением отправки самих уведомлений с сервера, но думаю, что для одной статьи этого пока достаточно.

Исходные коды получившегося приложения
GCM Architectural Overview
GCM Advanced Topics
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 16

    –1
    А теперь и Серверный PHP: github.com/mwillbanks/Zend_Mobile/
      0
      А опишите пожалуйста более понятно изменения которые касаются обычных пользователей андроида
        0
        Теперь одно приложение может получать уведомления сразу с нескольких серверов-отправителей. И еще теперь доступны уведомления с полезной нагрузкой, что позволит быстрее получать уведомления за счет ускоренного поедания батарейки.
        0
        А что будет со старыми приложениями?
          0
          C2DM полностью поддерживается для старых приложений, однако для новых приложений ключи можно получить только для GCM.
          0
          А как насчет надежности? Каков процент не доставленных уведомлений или уведомлений, доставленных с длительной задержкой?
            0
            GCM на сколько знаю работает начиная с Android 2.2…
            Функция полезная и думаю внедрить в будущий свой проект.
            За статью спасибо, только вопрос:
            Зачем пермишн на Wake-lock?
            <uses-permission android:name=«android.permission.WAKE_LOCK»/>
              0
              Да. GCM, как и C2DM, работают только с версии 2.2 и более.
              А Wake Lock нужен для того, чтобы приложение и сам GCM не засыпали.
                0
                то бишь для работы GCM телефон не должен спать вообще? Эта же технология рассчитана в 1 очередь на то время, когда приложение не запущенно…
                  0
                  В оригинальном примере этого пермишена нет. developer.android.com/guide/google/gcm/gs.html
                    0
                    В оригинальном примере (android-sdk-windows\extras\google\gcm\samples\gcm-demo-client) как раз таки есть Wake Lock:
                        <!-- Keeps the processor from sleeping when a message is received. -->
                        <uses-permission android:name="android.permission.WAKE_LOCK" />
                    
                  +1
                  Не совсем так, само приложение будет спать, но GCM-часть (сервис) в фоне будет принимать запросы от GCM и предпринимать какие-либо действия. Подробнее об архитектуре в GCM Architectural Overview.
                    +1
                    WAKE_LOCK не нужен приложению чтобы использовать GCM
                      +1
                      Я тоже считаю что не нужен, да и как приложение спать, а сервис нет? вейк лок распространяется на всю систему, значит полностью аппарат не будет спать. Плюс в примере кроме его указания он не используется, так что лучше со статьи убрать его.
              +1
              Насчет WakeLock-разрешения описал в своей статье Подробнее о реализации поддержки GCM на Android-клиенте. Если кратко: то это разрешение нужно, если будете пользоваться стандартной библиотекой от Google, но её исходные коды открыты — так что можно от него избавиться, если есть желание

              Only users with full accounts can post comments. Log in, please.