Skip to content

Instantly share code, notes, and snippets.

@akatasonov
Last active September 24, 2015 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akatasonov/f5d6efd448f49b3f6c95 to your computer and use it in GitHub Desktop.
Save akatasonov/f5d6efd448f49b3f6c95 to your computer and use it in GitHub Desktop.
Example of implementation of Google Cloud Messaging for Android
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="com.katasonov.everporter.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.katasonov.everporter.permission.C2D_MESSAGE" />
<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.katasonov.everporter" />
</intent-filter>
</receiver>
<service
android:name=".GcmService"
android:exported="false" >
</service>
package com.katasonov.everporter;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
public GcmBroadcastReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(), GcmService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
package com.katasonov.everporter;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.gcm.GoogleCloudMessaging;
/**
* An {@link IntentService} subclass for handling Google Cloud Messages in
* a service on a separate handler thread.
* <p/>
*/
public class GcmService extends IntentService {
private static final String TAG = "GcmService";
public static final int NOTIFICATION_ID = 1;
public GcmService() {
super("GcmService");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent we 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, we just ignore
* any message types we're not interested in, or that we don't
* recognize.
*/
switch (messageType) {
case GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR:
Log.i(TAG, "Send error: " + extras.toString());
break;
case GoogleCloudMessaging.MESSAGE_TYPE_DELETED:
Log.i(TAG, "Deleted messages on server: " + extras.toString());
break;
// If it's a regular GCM message, do some work.
case GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE:
// Post notification of received message.
Log.i(TAG, "Received: " + extras.toString());
String cmd = extras.getString("cmd", "");
// there are two type of messages - a command message and a message
if (cmd.isEmpty()) {
// not a command message, show notification
sendNotification(extras.getString("message"), extras.getString("urlOrder"));
} else {
switch (cmd) {
case "sendCurrentPosition":
Intent serviceIntent = new Intent(this, LocationService.class);
serviceIntent.putExtra("sendCurrentLocation", true);
startService(serviceIntent);
break;
}
}
break;
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
// Put the message into a notification and post it.
private void sendNotification(String msg, String msgURL) {
NotificationManager notificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, SigninActivity.class).putExtra("msgURL", msgURL),
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ep)
.setContentTitle("Everporter")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + getPackageName() + "/raw/notification"))
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
.setAutoCancel(true);
builder.setContentIntent(contentIntent);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
}
@Override
public void onConnected(Bundle connectionHint) {
// Connected to Google Play services!
Log.d(TAG, "connected to Google Play services");
startLocationService();
if (mUserID > 0) { // if the user has registered already, because if not we can't save it
// check registration in GCM and register, if necessary
if (mGcm == null) {
mGcm = GoogleCloudMessaging.getInstance(this);
mGcmRegistrationID = getRegistrationID();
}
if (mGcmRegistrationID.isEmpty()) {
registerInBackground();
}
}
}
/**
* Gets the current registration ID for application on GCM service, if there is one.
* <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() {
String registrationID = mPrefs.getString("GcmRegistrationID", "");
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 = mPrefs.getInt("appVersion", Integer.MIN_VALUE);
int currentVersion = getAppVersion(getApplicationContext());
if (registeredVersion != currentVersion) {
Log.i(TAG, "App version changed.");
return "";
}
return registrationID;
//return "";
}
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration ID and the app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
boolean result;
try {
Context context = getApplicationContext();
if (mGcm == null) {
mGcm = GoogleCloudMessaging.getInstance(context);
}
mGcmRegistrationID = mGcm.register(GCM_SENDER_ID);
Log.i(TAG, "Device registered, registration ID " + mGcmRegistrationID);
// Send the registration ID to your server over HTTP, so it
// can use GCM/HTTP or CCS to send messages to our app.
APIService.startActionSetGoogleToken(getApplicationContext(),
mReceiver, mUserCookieString, mUserID, mGcmRegistrationID);
// Persist the mGcmRegistrationID- no need to register again.
int appVersion = getAppVersion(context);
Log.i(TAG, "Saving GCM registration ID on app version " + appVersion);
SharedPreferences.Editor editor = mPrefs.edit();
editor.putString("GcmRegistrationID", mGcmRegistrationID);
editor.putInt("appVersion", appVersion);
editor.apply();
result = true;
} catch (IOException e) {
Log.e(TAG, "Error registering with GCM, " + e.getMessage());
result = false;
// 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 result;
}
}.execute(null, null, null);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment