gcm-slides



gcm-slides

0 0


gcm-slides

An introduction to GCM

On Github padc / gcm-slides

Google Cloud Messaging

Alternatives

Polling

WebSockets

Server Side Event

What is GCM?

Features

  • No sign up
  • No quotas
  • Battery efficiency
  • Supports JSON and plaintext

Caveats

  • Requires the user to set up a Google account
  • Message delivery is NOT guaranteed

GCM vs C2DM

  • Simple API key from Google API console page
  • Sender ID is the project id rather than email address
  • Supports JSON and plaintext
  • Multicast message
  • Multiple senders
  • Messages have Time To Live
  • 4kb max payload size

Why GCM?

  • Scalability and extensibility
  • Better use of device resources
  • Cheaper than SMS
  • No need to implement message queue
  • Simpler application design

Architecture

Architecture

  • Server sends message to GCM server
  • GCM queues message
  • GCM sends message if device is online
  • Android receives message and sends a broadcast
  • App wakes up
  • App processes the message

Device Requirements

  • At least Froyo
  • Google play services
  • Google account

Server Requirements

  • Able to store GCM registration ID
  • Exponential backoff in case GCM server is down
  • The usual request - response handling

Implementation

Manifest

<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.hastagqq.app" />
    </intent-filter>
</receiver>

<service android:name=".GcmIntentService" />
<meta-data android:name="com.google.android.gms.version"
           android:value="@integer/google_play_services_version" />

Broadcast Receiver

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    private static final String TAG = GcmBroadcastReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());

        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

Intent Service

public class GcmIntentService extends IntentService {
    private static final String TAG = GcmIntentService.class.getSimpleName();

    public static final int NOTIFICATION_ID = 1;

    public GcmIntentService() {
        super(Constants.SENDER_ID);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        String messageType = gcm.getMessageType(intent);

        if (extras != null && !extras.isEmpty()) {
            if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                sendNotification(getString(R.string.msg_view_news));
            }
        }

        GcmBroadcastReceiver.completeWakefulIntent(intent);
    }

    ...
}

Intent Service cont.

    private void sendNotification(String msg) {
        NotificationManager notificationManager = (NotificationManager)
                this.getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                 .setSmallIcon(R.drawable.ic_launcher)
                 .setContentTitle(getString(R.string.msg_new_news))
                 .setStyle(new NotificationCompat.BigTextStyle()
                         .bigText(msg))
                 .setContentText(msg);

        builder.setContentIntent(contentIntent);
        notificationManager.notify(NOTIFICATION_ID, builder.build());
    }

Server

from gcm import GCM

gcm = GCM("YOUR_SERVER_KEY")


def send_gcm(db, location, message, gcm_id=None):
    clients = [
        device.gcm_id
        for device in db.query(Device).filter(Device.location == location)
    ] if gcm_id is None and gcm_id == '' else [gcm_id]

    gcm.json_request(registration_ids=clients, data=message)

Server cont.

class DeviceRegistrationHandler(web.RequestHandler):
    def post(self):

        ...

        gcm_message = {
            'message': "New news item in your location.",
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())
        }

        db.query(News).filter(News.location == location).count() > 0\
            and send_gcm(db, location, gcm_message, gcm_id=device.gcm_id)

Other Alternatives

  • Firebase
  • Parse?
  • Socket.io
  • Autobahn

Who am I?

  • Evan Dale Aromin
  • coins.ph
  • Android, Python, NodeJS
  • @avendael
  • avendael.com

Thanks!!!