Reputation: 34497
Hello we are working on an android application in which GCM plays very important role in such as marketing purpose, push some important information to users etc.
It's working fine in 60-70% cases but other 30-40% it does not work. So rest of users never receive any notification which is useful for only to them.
This is the reason we are loosing users everyday. Below is my code to get the registration ID of GCM.
String msg = "";
int exceptionOccurRetry = 0;
while (exceptionOccurRetry < 5) {
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
int retry = 0;
while (retry < 5 && regid.length() == 0) {
regid = gcm.register(SENDER_ID);
++retry;
}
msg = "Device registered, registration ID=" + regid;
if (!regid.equals("")) {
// 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();
}
break;
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
exceptionOccurRetry++;
}
}
We are looking what are the reasons such that GCM id is not available for some users.
We know only one reason that If user device doesn't have a Google Play Services installed on user phone then it does not work.
We are looking some more reasons to solve this problem.
Upvotes: 12
Views: 1617
Reputation: 15668
One of the most common reasons why it is not available is that the user does not have google play services installed or is using a blocker.
You should also note that the GCM id should be refreshed if your application version has changed. You should be saving a unique device id to SharedPreferences
and always check if it is the same, otherwise you should initiate the registration process again.
It is also a good idea to refresh the id from time to time.
Upvotes: 2
Reputation: 340
How about the backend? If you delete the ID from the server's database, the user will never receive a notification unless you update the app version?
Upvotes: 1
Reputation: 4774
Is that piece of code inside an asyncTask if not that might be your error in certain version (dont remember which) gcm registration gives NetworkOnMainThreadException for some reason, they updated that later but I had that same problem some time ago, this is the piece of code I have used hope it helps you out:
private void performRegisterGCM(){
//Check for GCM availability
if(checkPlayServices(this)){
// If this check succeeds, proceed with normal processing.
// Otherwise, prompt user to get valid Play Services APK.
gcm = GoogleCloudMessaging.getInstance(this);
String regId = mPreferences.getGcmRegistrationId();
if (regId.isEmpty()){
RegisterGCM();
}else{
log.d("regId: "+regId);
}
} else {
// Status is a random integer
GooglePlayServicesUtil.getErrorDialog(status, this, RQS_GooglePlayServices).show();
}
}
public static boolean checkPlayServices(Activity mActivity){
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
return resultCode == ConnectionResult.SUCCESS
}
private void RegisterGCM(){
new AsyncTask<Void,Void,String>() {
@Override
protected String doInBackground(Void... params) {
String regid = "";
try{
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(mContext);
}
regid = gcm.register(Util.SENDER_ID);
}catch(Exception e){
log.e(e.getMessage());
}
return regid;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mPreferences.setGcmRegistrationId(s);
//TODO send regid to server with all the other info
sendGCMIDtoBackend(s);
}
}.execute(null, null, null);
}
Note that the checkPlayServices also gave me a lot of problems I had it like this:
public static boolean checkPlayServices(Activity mActivity){
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
if(resultCode!= ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)){
GooglePlayServicesUtil.getErrorDialog(
resultCode,
mActivity,
PLAY_SERVICES_RESOLUTION_REQUEST
).show();
} else{
log.d("DEVICE NOT SUPPORTED");
exit(true);
}
return false;
}
return true;
}
Then changed it as you can see in the first piece of code, because for some reason when it falls in isUserRecoverableError(result) it gives a lot of headaches... Everything here is from an actual working project and the code snippets were obtained in http://developer.android.com/google/gcm/client.html and modified to work correctly. Hope this helps you out, Good Luck...
Upvotes: 1
Reputation: 54
If your question all focus on the id registration you can ignore my answer.. Sorry my answer may be the wrong answer to your question.
I just want to show there may be some other 'factor' influence the message delivery..
Do your send all message on only single recipients?
One of the most useful features in GCM is support for up to 1,000 recipients for a single message. http://developer.android.com/training/cloudsync/gcm.html#
Sometimes our PHP also lose message sending to the registered device...
The message must less than 4K(do your GCM contains Pictures?)
You may have already read this..
Implementing GCM Client on Android
Upvotes: 1
Reputation: 646
Check if app was updated; if so, it must clear the registration ID since the existing registration ID is not guaranteed to work with the new app version.
When the application version changes, the registration id should change too. so you should save the last registration id to backend size. Maybe your problem is this.
Upvotes: 1
Reputation: 1843
if gcm id is null try to start a background task and get the id.check the below code
private void registerInBackground() {
new AsyncTask() {
@Override
protected String doInBackground(Object[] params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
sendRegistrationIdToBackend();
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
@Override
protected void onPostExecute(Object msg) {
// mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
Upvotes: 1
Reputation: 3273
Our team members are trying to send the notification, if it fails, they wait about 60 miliseconds or seconds (i'm not sure) for this push notification to be send again, if it still does not work, they wait twice the time, and so on ...
And you have to evaluate the response from google, there is a error string under:
std::string error = response["results"][0]["error"].asString();
Which gives you the information if a users account has been moved to, if so you can use:
Json::Value newRegistrationId = response["results"][0]["registration_id"];
to get the new ID.
Upvotes: 1