Last active
August 29, 2015 14:20
-
-
Save emanueleDiVizio/31d05d0e5ae6843ce361 to your computer and use it in GitHub Desktop.
Base classes to handle GCM registration and notifications.
This file contains hidden or 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
<manifest ...> | |
... | |
<uses-permission android:name="android.permission.WAKE_LOCK" /> | |
<permission android:name="your.package.name.permission.C2D_MESSAGE" | |
android:protectionLevel="signature" /> | |
<uses-permission android:name="your.package.name.permission.C2D_MESSAGE" /> | |
<uses-permission | |
android:name="com.google.android.c2dm.permission.RECEIVE" /> | |
.... | |
<application ...> | |
... | |
<receiver | |
android:name="path.to.GcmBroadcastReceiver" | |
android:permission="com.google.android.c2dm.permission.SEND" > | |
<intent-filter> | |
<!-- Receives the actual messages. --> | |
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> | |
<category android:name="your.package.name" /> | |
</intent-filter> | |
</receiver> | |
<service android:name="path.to.GcmIntentService" /> | |
... | |
</application> | |
</manifest> | |
This file contains hidden or 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
/* | |
* Copyright 2013 Google Inc. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import android.app.Activity; | |
import android.content.ComponentName; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.support.v4.content.WakefulBroadcastReceiver; | |
/** | |
* This {@code WakefulBroadcastReceiver} takes care of creating and managing a | |
* partial wake lock for your app. It passes off the work of processing the GCM | |
* message to an {@code IntentService}, while ensuring that the device does not | |
* go back to sleep in the transition. The {@code IntentService} calls | |
* {@code GcmBroadcastReceiver.completeWakefulIntent()} when it is ready to | |
* release the wake lock. | |
*/ | |
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
// Explicitly specify that GcmIntentService will handle the intent. | |
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); | |
} | |
} |
This file contains hidden or 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
/* | |
* Copyright (C) 2013 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import android.app.IntentService; | |
import android.app.NotificationManager; | |
import android.app.PendingIntent; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.os.Bundle; | |
import android.os.SystemClock; | |
import android.support.v4.app.NotificationCompat; | |
import android.util.Log; | |
import com.google.android.gms.gcm.GoogleCloudMessaging; | |
/** | |
* This {@code IntentService} does the actual handling of the GCM message. | |
* {@code GcmBroadcastReceiver} (a {@code WakefulBroadcastReceiver}) holds a | |
* partial wake lock for this service while the service does its work. When the | |
* service is finished, it calls {@code completeWakefulIntent()} to release the | |
* wake lock. | |
*/ | |
public class GcmIntentService extends IntentService { | |
public static final int NOTIFICATION_ID = 1; | |
private NotificationManager mNotificationManager; | |
NotificationCompat.Builder builder; | |
public GcmIntentService() { | |
super("GcmIntentService"); | |
} | |
public static final String TAG = "GCM Demo"; | |
@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. | |
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. | |
*/ | |
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. | |
} 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); | |
} | |
// TODO: Build notficiation. | |
private void sendNotification(String msg) { | |
mNotificationManager = (NotificationManager) | |
this.getSystemService(Context.NOTIFICATION_SERVICE); | |
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, | |
new Intent(this, PushRegisterHelper.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()); | |
} | |
} |
This file contains hidden or 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
/* | |
* Copyright 2013 Google Inc. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import android.content.Context; | |
import android.content.SharedPreferences; | |
import android.content.pm.PackageInfo; | |
import android.content.pm.PackageManager.NameNotFoundException; | |
import android.os.AsyncTask; | |
import android.util.Log; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.GooglePlayServicesUtil; | |
import com.google.android.gms.gcm.GoogleCloudMessaging; | |
import java.io.IOException; | |
/** | |
* Helper class for registering device to GCM. | |
*/ | |
public class PushRegisterHelper { | |
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 static final 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." | |
*/ | |
String SENDER_ID = "xxxxxxx"; | |
/** | |
* Tag used on log messages. | |
*/ | |
static final String TAG = "GCM Demo"; | |
private OnAppRegisteredListener onAppRegisteredListener; | |
private PlayServiceErrorListener playServiceErrorListener; | |
private GoogleCloudMessaging gcm; | |
private Context context; | |
private String regid; | |
public PushRegisterHelper(Context context) { | |
this.context = context; | |
} | |
/** | |
* | |
* Register device to google's GCM. | |
*/ | |
public void registerToGCM(){ | |
// Check device for Play Services APK. If check succeeds, proceed with GCM registration. | |
if (checkPlayServices()) { | |
gcm = GoogleCloudMessaging.getInstance(context); | |
regid = getRegistrationId(context); | |
if (regid.isEmpty()) { | |
registerInBackground(); | |
} | |
} else { | |
Log.i(TAG, "No valid Google Play Services APK found."); | |
} | |
} | |
/** | |
* 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. | |
*/ | |
private boolean checkPlayServices() { | |
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context); | |
if (resultCode != ConnectionResult.SUCCESS) { | |
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { | |
playServiceErrorListener.onPlayServiceError(resultCode); | |
//TODO: Put this in the calling context to handle playyServiceError | |
/*GooglePlayServicesUtil.getErrorDialog(resultCode, context, | |
PLAY_SERVICES_RESOLUTION_REQUEST).show();*/ | |
} else { | |
Log.i(TAG, "This device is not supported."); | |
} | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Stores the registration ID and the app versionCode in the application's | |
* {@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.apply(); | |
} | |
/** | |
* 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(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 regID is not guaranteed to work with the new | |
// app version. | |
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; | |
} | |
/** | |
* 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, String>() { | |
@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, so it | |
// can use GCM/HTTP or CCS to send messages to your app. | |
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. | |
// Persist the regID - no need to register again. | |
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) { | |
onAppRegisteredListener.onAppRegistered(regid); | |
} | |
}.execute(null, null, null); | |
} | |
/** | |
* @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); | |
} | |
} | |
/** | |
* @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 regID in your app is up to you. | |
return context.getSharedPreferences(PushRegisterHelper.class.getSimpleName(), | |
Context.MODE_PRIVATE); | |
} | |
/** | |
* 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. | |
*/ | |
private void sendRegistrationIdToBackend() { | |
//TODO: Register to server. | |
} | |
/** | |
* | |
* Callback setters. | |
* | |
*/ | |
public void setOnAppRegisteredListener(OnAppRegisteredListener onAppRegisteredListener) { | |
this.onAppRegisteredListener = onAppRegisteredListener; | |
} | |
public void setPlayServiceErrorListener(PlayServiceErrorListener playServiceErrorListener) { | |
this.playServiceErrorListener = playServiceErrorListener; | |
} | |
/** | |
* | |
* Callback interfaces | |
* | |
*/ | |
public interface OnAppRegisteredListener{ | |
public void onAppRegistered(String regId); | |
} | |
public interface PlayServiceErrorListener{ | |
public void onPlayServiceError(int resultcode); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment