I am working with google push notifications. i am able to retrieve my reg id but its failing to register my mobile in server.Can someone help me where am i going wrong
Main Activity:
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);
//setContentView(R.layout.activity_main);
// mDisplay = (TextView) findViewById(R.id.display);
registerReceiver(mHandleMessageReceiver,
new IntentFilter(DISPLAY_MESSAGE_ACTION));
final String regId = GCMRegistrar.getRegistrationId(this);
mDisplay.append("Reg id" + regId + " ");
if (regId.equals("")) {
// Automatically registers application on startup.
GCMRegistrar.register(this, SENDER_ID);
//mDisplay.append("Reg id" + regId + " ");
} else {
// Device is already registered on GCM, check server.
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
//mDisplay.append(getString(R.string.already_registered) +
"\n");
// mDisplay.append("Reg id" + regId + " ");
} 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.
// mDisplay.append("Reg id" + regId + " ");
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
boolean registered =
ServerUtilities.register(context, regId,
userNum);
// 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);
}
}
Server Utilities:
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(TAG, "Attempt #" + i + " to register");
try {
displayMessage(context, context.getString(
R.string.server_registering, i, MAX_ATTEMPTS));
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
String message = context.getString(R.string.server_registered);
CommonUtilities.displayMessage(context, message);
return true;
} catch (IOException e) {
// Here we are simplifying and retrying on any error; in a real
// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(TAG, "Failed to register on attempt " + i, e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return false;
}
// increase backoff exponentially
backoff *= 2;
}
}
server and sender id:
static final String SERVER_URL = "http://http://xxx.xxx.xxx.xxx:8080/Sample";
/**
* Google API project id registered to use GCM.
*/
static final String SENDER_ID = "921198929963";
Error log:
01-21 15:32:59.359 19009-19090/? E/GCMRegistrar: internal error: retry
receiver class not set yet
01-21 15:32:59.365 19009-19090/? E/Regid:
APA91bEpJzZoMsj10CzBHXIAxmkyJMyZXTyCUsihO_BhmB-noqc-Llu5uSiaXZBF-
ICCjHtwgNTysoOXyA9715U1kG4L2BV-Zl3vz5DOwk4mTYX9HdF5aBSaOzmLo9zE_ZDz-9ppnThi
01-21 15:32:59.988 19009-19090/? E/SurakshaGCM: Failed to register on
attempt 1
01-21 15:33:02.215 19009-19090/? E/SurakshaGCM: Failed to register on
attempt 2
01-21 15:33:06.647 19009-19090/? E/SurakshaGCM: Failed to register on
attempt 3
01-21 15:33:14.913 19009-19090/? E/SurakshaGCM: Failed to register on
attempt 4
Kindly use the latest gcm jar file. If you get the error "internal error: retry receiver class not set yet", then you have an older version of the client gcm.jar. You can download either the source or the updated gcm.jar from the GCM repository.
You may use this tutorial as your guide, the project contains client libraries and samples to explore the GCM APIs: https://github.com/google/gcm
Related
I recently began working with Google Cloud Messaging for push notifications. I have an app that I have not released a signed apk for (information provided in case there is some detection of dev builds) and have not reinstalled the app in any way shape or form.
My app requests a registration ID, I store it manually while the server side is being worked on, and test with a small bit of code on the server that is set up to send push notifications. It works for the bulk of the day but the following morning I get a response "{ error: 'NotRegistered' }".
I have taken no actions to unregister the device and the app version has not changed.
[edit] Added relevant bits from Android Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Stuff for push notifications -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="com.my.package.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.my.package.permission.C2D_MESSAGE" />
<!-- end push notifications stuff -->
public void onResume(){
super.onResume();
/**
* Check for Google Play Services APK
*/
if(myApp.checkPlayServices(this)){
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(getApplicationContext());
if( regid == null || regid.isEmpty() || (myApp.getSP().getInt(Constants.PROPERTY_APP_VERSION,-1) <= getAppVersion(this)) ){
registerInBackground();
} else {
L.i("Using GCM ID:" + regid);
}
} else {
L.i("No valid Google Play Services APK found.");
}
IntentFilter intentFilter = new IntentFilter("com.google.android.c2dm.intent.RECEIVE");
gcmReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String[] params = {extras.getString("imgUrl"), gcm.getMessageType(intent), extras.toString()};
new GCMReceiverTask().execute(params);
}
};
this.registerReceiver(gcmReceiver,intentFilter);
}
/**
* Stuff pertaining to push notifications
*/
String SENDER_ID = null;
String regid = null;
GoogleCloudMessaging gcm;
/**
* Gets the current registration ID for application on GCM service.
* <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 = myApp.getSP();
String registrationId = prefs.getString(Constants.PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
L.i("Registration not found.");
return "";
}
// 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.
int registeredVersion = prefs.getInt(Constants.PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
L.i("App version changed.");
return "";
}
return registrationId;
}
/**
* #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 (PackageManager.NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration ID and app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new GCMRegistrationTask().execute(null, null, null);
}
/**
* 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() {
// Your implementation here.
L.i("WOULD SEND REGISTRATION TO SERVER... " + regid);
}
/**
* Stores the registration ID and app versionCode in the application's
* {#code SharedPreferences}.
*
* #param regId registration ID
*/
private void storeRegistrationId(String regId) {
final SharedPreferences prefs = myApp.getSP();
int appVersion = getAppVersion(this);
L.i("Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Constants.PROPERTY_REG_ID, regId);
editor.putInt(Constants.PROPERTY_APP_VERSION, appVersion);
editor.commit();
}
/**
* Unregisters the application with GCM servers asynchronously.
* <p>
* Removes the registration ID and app versionCode from the application's
* shared preferences.
*/
private void unRegisterInBackground() {
new GCMRegistrationTask(true).execute(null, null, null);
}
private class GCMReceiverTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// Expect params[0] to be image URL, params[1] to be messageType
String imageUrl = params[0];
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(Main.this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = params[1];
// Stringified extras as last param
String extrasString = params[params.length - 1];
/*
* 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)) {
L.e("Send error: " + extrasString);
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
L.i("Deleted messages on server: " +
extrasString);
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// retrieve image
try {
L.i("Got image URL: " + imageUrl);
String[] parts = imageUrl.split("/");
String fileName = parts[parts.length - 1];
if (imageUrl.isEmpty()) {
throw new Exception("No Image URL supplied.");
}
ServerCall sc = new ServerCall(imageUrl, ServerCall.POST);
String path = Environment.getExternalStorageDirectory() + File.separator + getPackageName().toString() + File.separator + "user_images";
sc.saveByteArrayToLocalFile(path, fileName);
} catch (Exception e) {
L.e("ERROR writing image to storage: " + Log.getStackTraceString(e));
}
// Post notification of received message.
L.i("Received: " + extrasString);
}
return null;
}
#Override
protected void onPostExecute(String msg){
Button proceed = (Button)findViewById(R.id.button4);
if( proceed != null ){
proceed.setEnabled(true);
}
}
}
private class GCMRegistrationTask extends AsyncTask<Void, Void, String> {
private boolean unregistering = false;
GCMRegistrationTask() {
this(false);
}
GCMRegistrationTask(boolean unregister) {
super();
this.unregistering = unregister;
}
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
}
if( unregistering ) {
gcm.unregister();
myApp.getSP()
.edit()
.remove(Constants.PROPERTY_REG_ID)
.commit();
} else {
SENDER_ID = myApp.getSP().getString(Constants.GCM_SENDER_ID,null);
if( SENDER_ID != null ) {
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.
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 registration ID - no need to register again.
storeRegistrationId(regid);
} else {
L.e("SHOULD NOT GET HERE, GCM_SENDER_ID SHOULD NOT BE NULL! " + myApp.getSP().getString(Constants.GCM_SENDER_ID,"[[EMPTY]]"));
}
}
} 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) {
// handle postExecute - Nothing to do?
}
}
This is intentional.
Registration IDs will expire after some time. Client should detect that and request another ID.
http://developer.android.com/google/gcm/client.html
As stated above, an Android app must register with GCM servers and get a registration ID before it can receive messages. A given registration ID is not guaranteed to last indefinitely, so the first thing your app should always do is check to make sure it has a valid registration ID (as shown in the code snippets above).
Implicit intents with startService are not safe: Intent { act=com.google.android.c2dm.intent.REGISTRATION (has extras) } android.content.ContextWrapper.startService:494 in.demo.gcm.MainActivity$1.onClick:29 android.view.View.performClick:4438
I am getting above error,i add gcm.jar in my project but still my error not clear.
Please give me any other suggestion.
Thanks in advance.
I don't know about the error you are getting, but gcm.jar is obsolete. The recommended way to register to GCM is via the GoogleCloudMessaging.register method of the Google Play Services library.
The registration code (taken from the official GCM demo app) looks like this :
/**
* 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);
}
I'm following the android GCM tutorial provided by google, and I get the following errors:
on the line:
private void sendRegistrationIdToBackend() {
// Your implementation here.
}
Syntax error on Token "Void", # expected.
Syntax error insert "enum Identifier" to complete EnumHeader.
Using, compiler 1.6
Thank you so much.
The entire function:
private void registerInBackground() {
new AsyncTask() {
#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.
// The request to your server should be authenticated if your app
// is using accounts.
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);
/**
* 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() {
// Your implementation here.
}
}
It seems you forgot to close the registerInBackground() method.
Add } after }.execute(null, null, null);
Another way to look at it is that you put private void sendRegistrationIdToBackend() {} inside the registerInBackground() method, which is wrong.
hello i am following the official documentation of android to send the push notification as the old method is deprecated but im facing problem in implementing GCM Client
http://developer.android.com/google/gcm/client.html
the tutorial is written here, scroll down and see
private void registerInBackground()
when i write this function on my app it gives me this error
Syntax error on token "void", # expected
i have googled it and i know the error now that this method is trying to create a method inside a method but still im confused because it is the official documentation i must have done something wrong, can anybody point out plz?
here is the method on this tutorial:
private void registerInBackground() {
new AsyncTask() {
#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.
// The request to your server should be authenticated if your app
// is using accounts.
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);
...
/**
* 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() {
// Your implementation here.
}
}
now see that sendRegistrationIdToBackend is inside a method itself, any help plz?
here is the solution i found for it and disappointed that 33 people viewed it but nobody bother to ans anyways here is the code
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);
}
I,m developing GCM app and recieve "error:AUTHENTICATION_FAILED". I,m using my samsung tab device.My code is below:
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
Log.i(TAG, "11111");
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
Log.i(TAG, "11dfsfsd111");
}
Log.i(TAG, "11dfsfsd111fsdfsdf");
regid = gcm.register(SENDER_ID);
Log.i(TAG, "id = :"+regid);
Log.i(TAG, "2222");
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) {
Log.i(TAG, "sdfdsfs:" + msg);
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
i Get this msg when the control comes in postExecute function and print the "msg" variable. I searched for the error and found that this error come due to wrong password of gmail sync acount, But i checked it and my password is correct. Kindly help
public void registerClient() {
try {
// Check that the device supports GCM (should be in a try / catch)
GCMRegistrar.checkDevice(viewLogin);
// Check the manifest to be sure this app has all the required
// permissions.
GCMRegistrar.checkManifest(viewLogin);
// Get the existing registration id, if it exists.
regId = GCMRegistrar.getRegistrationId(viewLogin);
if (regId.equals("")) {
registrationStatus = "Registering...";
// register this device for this project
GCMRegistrar.register(viewLogin, GCMIntentService.PROJECT_ID);
regId = GCMRegistrar.getRegistrationId(viewLogin);
registrationStatus = "Registration Acquired";
// This is actually a dummy function. At this point, one
// would send the registration id, and other identifying
// information to your server, which should save the id
// for use when broadcasting messages.
} else {
registrationStatus = "Already registered";
}
Log.d(TAG, regId);
sendRegistrationToServer();
} catch (Exception e) {
e.printStackTrace();
registrationStatus = e.getMessage();
}
Log.d(TAG, registrationStatus);
// This is part of our CHEAT. For this demo, you'll need to
// capture this registration id so it can be used in our demo web
// service.
}
please use this..its working in my project.
add in your manifestfile:
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
I think you are using old GCM implementation. New GCM implementation code is available on developer site(http://developer.android.com/google/gcm/client.html). Account authentication and other type of authentication is properly handled here