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);
}
Related
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
I am using Windows Azure notification hub to send notifications to the users in my Android application. I have some kind of a chat in my application, and I would like to send notifications only to specific users. I suppose that I have to specify their tags when sending notifications. Where are those tags stored? How am I sure that the user is properly registered?
I have this code for registering users:
#SuppressWarnings("unchecked")
private void registerWithNotificationHubs() {
new AsyncTask() {
#Override
protected Object doInBackground(Object... params) {
try {
String regid = gcm.register(SENDER_ID);
hub.register(regid, "tag");
} catch (Exception e) {
return e;
}
return null;
}
}.execute(null, null, null);
}
When not using a tag, the notifications work and they are sent to all the devices. I'd like to add a tag and send the notification to specific tag.
We call it tags not tokens. You can specify one ore more tags for each device registration and then use those tags to rout messages to particular user or group. Documentation id here.
I am developing app on GCM already i have registered in GCM. But after seven days the keyID is expiring. After expiring the app is again start from first onwords from registering..
My code for checking registration
if (GCMRegistrar.isRegisteredOnServer(First.this)) {
// Skips registration.
Intent regact = new Intent(SplashScreen.this,
LoginScreen.class);
startActivity(regact);
Toast.makeText(getApplicationContext(),
"Already registered with GCM",
Toast.LENGTH_LONG).show();
} else {
Intent mainact = new Intent(SplashScreen.this,
MainActivity.class);
startActivity(mainact);
Toast.makeText(getApplicationContext(),
"Have to Register with GCM",
Toast.LENGTH_LONG).show();
}
This is condition for checking the GCM for registered or not. After seven days it is getting unregistered please help me i cant find the solution...
Thanks in advance...
try below code..
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
// Automatically registers application on startup.
GCMRegistrar.register(this, SENDER_ID);
} else {
// save your id
}
GCMRegistrar is a deprecated class which you don't have to use anymore. Even if you choose to continue using that class, you don't have to use isRegisteredOnServer. That method (as you can see below), would return false after 7 days pass since you sent the registration ID to your server. That doesn't mean the registration ID expired. It's only meant to make sure that if your server somehow loses the registration ID, it will receive it again after 7 days. If your server is reliable enough, you don't need to rely on this artificial expiration.
/**
* Checks whether the device was successfully registered in the server side,
* as set by {#link #setRegisteredOnServer(Context, boolean)}.
*
* <p>To avoid the scenario where the device sends the registration to the
* server but the server loses it, this flag has an expiration date, which
* is {#link #DEFAULT_ON_SERVER_LIFESPAN_MS} by default (but can be changed
* by {#link #setRegisterOnServerLifespan(Context, long)}).
*/
public static boolean isRegisteredOnServer(Context context) {
final SharedPreferences prefs = getGCMPreferences(context);
boolean isRegistered = prefs.getBoolean(PROPERTY_ON_SERVER, false);
Log.v(TAG, "Is registered on server: " + isRegistered);
if (isRegistered) {
// checks if the information is not stale
long expirationTime =
prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
if (System.currentTimeMillis() > expirationTime) {
Log.v(TAG, "flag expired on: " + new Timestamp(expirationTime));
return false;
}
}
return isRegistered;
}
If you choose to stop using GCMRegistrar, as is recommended by Google, you can simply use the GoogleCloudMessaging.register method to register. That's a blocking method, so you shouldn't run it on the main thread. You should store the returned registration ID in your shared preferences, and only register again when a new version of your app is installed. This demo will show you how to do it.
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.