Last active
September 24, 2015 13:08
-
-
Save akatasonov/f5d6efd448f49b3f6c95 to your computer and use it in GitHub Desktop.
Example of implementation of Google Cloud Messaging for Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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