I am using eclipse IDE for development. I followed lots of tutorials and implemented push notifications in my project but I'm not getting the GCM Registration id, So my questions is: will eclipse support the push notifications or not?
Below is the code snippet; if you need more clarity please comment below.
registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
Log.v("testing", "testing");
// Get GCM registration id
final String regId = GCMRegistrar.getRegistrationId(this);
Log.v("regId", regId);
// Check if regid already presents
if (regId.equals("")) {
// Registration is not present, register now with GCM
Log.v("registerd","am here");
GCMRegistrar.register(this, SENDER_ID);
} else {
// Device is already registered on GCM
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
Toast.makeText(getApplicationContext(), "Already registered with GCM", Toast.LENGTH_LONG).show();
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
Log.v("hello","am here");
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// Register on our server
// On server creates a new user
ServerUtilities.register(context, name, email, regId);
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
Push notifications will work no matter what IDE you're using, but I have two pieces of advice for you:
You need to migrate your project to Android Studio for better support.
Your GCM registration library GCMRegistrar is too old. You need to get the latest version, checkout here.
Hope this helped :)
Finally got the answer by using following tutorial.. link
Related
Last year when you added a Cloud Endpoints plus GCM module to an Android Studio project, the IDE created some sample code both in the backend and the app that showed how to use GCM with Cloud Endpoints.
However, with the newer versions of Android Studio you only get the backend part added for you. So I went back into my old projects and dug up some of the convenient app code which registered, and sent GCM push notifications in Android.
Here is what that code looks like:
GcmBroadcastReceiver.java
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);
}
}
GcmIntentService.java
public class GcmIntentService extends IntentService {
android.support.v4.app.NotificationCompat.Builder notification;
public GcmIntentService() {
super("GcmIntentService");
}
#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 != null && !extras.isEmpty()) { // has effect of unparcelling Bundle
// Since we're not using two way messaging, this is all we really to check for
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
Logger.getLogger("GCM_RECEIVED").log(Level.INFO, extras.toString());
showToast(extras.getString("message"));
sendNotification(extras.getString("message"));
}
}
//call to the API and get new data.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
protected void showToast(final String message) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
});
}
private void sendNotification(String msg) {
notification = new android.support.v4.app.NotificationCompat.Builder(this);
//set number of notifications count
//notification.setNumber(x);
//cancels notification when app is opened.
notification.setAutoCancel(true);
//build the notification
notification.setSmallIcon(R.drawable.greenicon);
notification.setTicker("This is the ticker!");
//set time
notification.setWhen(System.currentTimeMillis());
notification.setContentTitle("New message!");
notification.setContentText(msg);
notification.setSound((Settings.System.DEFAULT_NOTIFICATION_URI));
//LED
notification.setLights(Color.RED, 3000, 3000);
// intent
Intent intent = new Intent(this, MainActivity.class);
//give phone access to perform this intent b/c they may be in another part of their phone.
//aka gives phone access to the intents in our app
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//what to do when notification is clicked:
notification.setContentIntent(pendingIntent);
//Builds notification and issues it (sends it to device). Can build and send out notifcations
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//send out notification with uniqueID
nm.notify(2158, notification.build());
}
}
GcmRegistrationAsyncTask
class GcmRegistrationAsyncTask extends AsyncTask<Void, Void, String> {
private static Registration regService = null;
private GoogleCloudMessaging gcm;
private Context context;
// TODO: change to your own sender ID to Google Developers Console project number, as per instructions above
private static final String SENDER_ID = "1026567774990";
public GcmRegistrationAsyncTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(Void... params) {
if (regService == null) {
Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// Need setRootUrl and setGoogleClientRequestInitializer only for local testing,
// otherwise they can be skipped
.setRootUrl("https://push-notif-45657747.appspot.com/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest)
throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
}) ;
// end of optional local run code
regService = builder.build();
}
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
String 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.
// The request to your server should be authenticated if your app
// is using accounts.
regService.register(regId).execute();
} catch (IOException ex) {
ex.printStackTrace();
msg = "Error: " + ex.getMessage();
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
Logger.getLogger("REGISTRATION").log(Level.INFO, msg);
}
}
However, I am getting some deprecated errors in Android Studio now:
gcm.register(SENDER_ID); is deprecated and so is GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.
This GCM stuff is pretty confusing to begin with and while there is some information here on how to use it, I was wondering if anyone had any currently working non-deprecated examples or maybe you could suggest some edits to the above code if you know what you are doing...? Much thanks!
Wanted to give people a little guide here in case they were lost.
First check out and stay up to date with this Google Cloud Messaging Android example:
https://github.com/google/gcm
To make it work you will have to generate a google-services.json file which you can do here:
https://developers.google.com/mobile/add
Make sure you are logged into the google developers console before you go that link. It will load your projects for you and automatically set up the gcm api key for you in your projects credentials.
Copy/paste the google-services.json into the /app directory of your Android project.
Add a cloud endpoints with gcm module to the android project.
Enter your gcm api key (which you can view on your credentials page on developers console) into the webapp-WEB_INF/appengine-web.xml file in your cloud endpoints backend:
<property name="gcm.api.key" value="your-api-key-here"/>
This way, inside the Android client and MessagingEndpoint the code will automatically get the api key (in the endpoint it will be the line Sender sender = new Sender(API_KEY); for example, which will just retrieve it for you).
Run the sample gcm android project and it should work. Send a push notification with the API's explorer you deployed.
BIG NOTE: when you are ready to use the sample code in your own app make sure the RegistrationIntentService is in the root of your package or it won't work! Took a while to figure that out... Not sure if it is a bug or what.
I used this code to get gcm registration id. (Earlier)
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest was properly set - comment out this line
// while developing the app, then uncomment it when it's ready.
GCMRegistrar.checkManifest(this);
// registerReceiver(mHandleMessageReceiver, new IntentFilter(
// CommonUtilities.DISPLAY_MESSAGE_ACTION));
// Get GCM registration id
final String regId = GCMRegistrar.getRegistrationId(this);
// Check if regid already presents
if (regId.equals("")) {
// Registration is not present, register now with GCM
GCMRegistrar.register(this, CommonUtilities.SENDER_ID);
} else {
AppSharedPreferences.saveDeviceIDPreference(ctx, regId);
// Device is already registered on GCM
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
// Toast.makeText(getApplicationContext(), "Already registered with GCM", Toast.LENGTH_LONG).show();
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// Register on our server
// On server creates a new user
ServerUtilities.register(context, regId);
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
But, shockingly, it seems to change everytime on execution, for the same device and same application. Please let me know the possible reason of that.
EDITED
modified GCM to the newer version
gcm = GoogleCloudMessaging.getInstance(this);
new RegisterBackground().execute();
Followed this tutorial.
But, still same behaviour, i.e, getting new reg id on every install.
I am following this tutorial:
http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
my app is getting gcm_regid, that is stored in mysql. With this id, I can send message via php to chosen regid;
but when i deinstall the application - and reinstall, it get's a new reg_id - thats ok too, this is stored in mysql too.
But when I send a message to the first gcm_regid (this was it's previous gcm_regid) the phone is getting that message too, even it has got a new gcm_regid (due to reinstall) - why is that so, and how can I delete the previous id?
and where is that id? in my device? stored in gcm server?
and a second question:
do I have to take majour changes when I change GCMRegistrar in the tutorial above to Google Cloud Messaging - what I have to do there
When GCM assigns a new Registration ID to your device, the previous IDs that were assigned to it continue to work. If you send a message to an older Registration ID assigned to your device, the message will be delivered, but your server will get a response containing a canonical Regsitration ID, which is the newest Registration ID of that device. If you get such a response, you should delete the old Registration ID from your DB.
As for your second question, you don't have to make major changes in order to stop using GCMRegigtrar and use GoogleCloudMessaging instead. In fact, your code should look simpler after you make that change.
You'll have one call to GoogleCloudMessaging.register inside an AsyncTask in one of your activities. This method has to be called in an AsyncTask because it's blocking, so it can't be executed on the main thread. The good thing about it is that you get the response in the same place you call the method, and don't have to wait for it in the GCMBroadCastReceiver/IntentService.
Your GCMBroadcastReceiver/IntentService will have to handle just incoming messages. They won't have to deal with registration anymore.
Here's a partial example of the new registration process, taken from the official GCM Demo :
/**
* 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) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
On server side, i found for one device there multiple registration IDs, which obviously is creating for me lots of issues. like messages received many times.
How could I get red of old registration IDs, or make sure that registration doesn't happen if there a valid registration ID.
I follow the example tutorial on Android doc when I wrote my app as below:
checkNotNull(SERVER_URL, "SERVER_URL");
checkNotNull(SENDER_ID, "SENDER_ID");
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest was properly set - comment out this line
// while developing the app, then uncomment it when it's ready.
// NOT required any more GCMRegistrar.checkManifest(this);
/**
* this code to register reciver moved to message actvity
*/
//registerReceiver(mHandleMessageReceiver, new IntentFilter(
// DISPLAY_MESSAGE_ACTION));
/* final String */regId = GCMRegistrar.getRegistrationId(this);
/**
* save regId in pref to be used by Location update service
*/
SavePreferences("regId", regId);
if (regId.equals("")) {
// Automatically registers application on startup.
GCMRegistrar.register(this, SENDER_ID);
} else {
// Device is already registered on GCM, check server.
if (GCMRegistrar.isRegisteredOnServer(this)) {
;;
// Skips registration.
// -- mDisplay.append(getString(R.string.already_registered) +
// "\n");
// System.out.println(getString(R.string.already_registered)
// + "\n");
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
boolean registered = ServerUtilities.register(context,
regId);
// At this point all attempts to register with the app
// server failed, so we need to unregister the device
// from GCM - the app will try to register again when
// it is restarted. Note that GCM will send an
// unregistered callback upon completion, but
// GCMIntentService.onUnregistered() will ignore it.
if (!registered) {
GCMRegistrar.unregister(context);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
Please refer link: http://stackoverflow.com/questions/15030233/gcm-multiple-application-id-in-server-side/15030465#comment21123039_15030465
Also check canonical registration ids concept :http://developer.android.com/google/gcm/adv.html
or
when a new id is generated you will try to register it GCM registrar. when this new registration id successfully register your onRegister() method of service will be called .
here you can add code to replace previous one with new one.but for this along with registration id you need to send some unique reference to server,so for next time you can check this unique reference and replace existing registration id with new one
checked following code:
#Override
protected void onRegistered(Context context, String registrationId) {
ServiceUtilities.register(context, registrationId);
//call service and replace id
}
I have been trying to get Google Cloud Messaging to create push notifications. I am able to register the device, store the registration id on the server, and then send the push message back to the device.
I am able to do all these and the catLog showed that the push message got to the device. But on the device the push notification message did not appear.
What could be the cause of this?
Just in case, here is how I register the device:
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals(""))
{
// Automatically registers application on startup.
GCMRegistrar.register(getApplicationContext(), SENDER_ID);
}
else
{
// Device is already registered on GCM, check server.
if (GCMRegistrar.isRegisteredOnServer(getApplicationContext()))
{
// Not sure what to do here :)
}
else
{
if ( user_id != null )
{
GCMRegistrar.register(this, SENDER_ID); // google register
setRegistrationId ( user_id , regId ); // saves id on server
}
}
}
End on onPostExecute I do GCMRegistrar.setRegisteredOnServer(getApplicationContext(), true);
Here is my onMessage() method in my GCMIntentService
#Override
protected void onMessage(Context ctxt, Intent message) {
Bundle extras=message.getExtras();
for (String key : extras.keySet()) {
Log.d(getClass().getSimpleName(),
String.format("onMessage: %s=%s", key,
extras.getString(key)));
}
}
Is this the problem maybe? How should it actually be?
Thank you!
What could be the cause of this?
Here are some possibilities:
You do not have a GCMIntentService subclass in your app.
You do, but it is not registered in the manifest.
You do, but you did not override onMessage()
You did, but your onMessage() is not properly logging the event or otherwise letting you know that the event occurred.