GCM does not send notifications

I created an application that uses GCM functionality. When I send a message from the server to the device in response, I get the message identifier. After sending a message from the server, when I start the application again, I get a response on the device. It does not come as a notification, such as a GMAIL notification after the application is installed, when the server sends a message on which the notification will be displayed. I am sending the complete server and client code. Please help me solve the problem.

The problem I received is:. When I run the Android application again, what I sent from the server side, it displays a message, but I want it to be like a notification that I am sending from the server ...

Server side code

/** * Servlet implementation class GCMBroadcast */ @WebServlet("/GCMBroadcast") public class GCMBroadcast extends HttpServlet { private static final long serialVersionUID = 1L; private static final String SENDER_ID = ""; private static final String ANDROID_DEVICE = ""; private List<String> androidTargets = new ArrayList<String>(); public GCMBroadcast() { super(); androidTargets.add(ANDROID_DEVICE); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String collapseKey = ""; String userMessage = ""; try { userMessage = request.getParameter("Message"); collapseKey = request.getParameter("CollapseKey"); } catch (Exception e) { e.printStackTrace(); return; } Sender sender = new Sender(SENDER_ID); Message message = new Message.Builder() .collapseKey(collapseKey) .timeToLive(30) .delayWhileIdle(true) .addData("message", userMessage) .build(); try { MulticastResult result = sender.send(message, androidTargets, 1); System.out.println("Response: " + result.getResults().toString()); if (result.getResults() != null) { int canonicalRegId = result.getCanonicalIds(); if (canonicalRegId != 0) { System.out.println("response " +canonicalRegId ); } } else { int error = result.getFailure(); System.out.println("Broadcast failure: " + error); } } catch (Exception e) { e.printStackTrace(); } request.setAttribute("CollapseKey", collapseKey); request.setAttribute("Message", userMessage); request.getRequestDispatcher("index.jsp").forward(request, response); } } 

Demo Activity Code

 public class DemoActivity extends Activity { 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 = ""; /** * Tag used on log messages. */ static final String TAG = "GCM Demo"; TextView mDisplay; GoogleCloudMessaging gcm; AtomicInteger msgId = new AtomicInteger(); Context context; String regid; @SuppressLint("NewApi") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDisplay = (TextView) findViewById(R.id.display); context = getApplicationContext(); // Check device for Play Services APK. If check succeeds, proceed with GCM registration. if (checkPlayServices()) { gcm = GoogleCloudMessaging.getInstance(this); regid = getRegistrationId(context); Log.d("Registration id ", regid+""); if (regid.isEmpty()) { registerInBackground(); } } else { Log.i(TAG, "No valid Google Play Services APK found."); } } @Override protected void onResume() { super.onResume(); // Check device for Play Services APK. checkPlayServices(); } /** * 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 system settings. */ private boolean checkPlayServices() { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) { GooglePlayServicesUtil.getErrorDialog(resultCode, this, PLAY_SERVICES_RESOLUTION_REQUEST).show(); } else { Log.i(TAG, "This device is not supported."); finish(); } return false; } return true; } /** * Stores the registration ID and the app versionCode in the application's * {@code SharedPreferences}. * * @param context application 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.commit(); } /** * 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. */ @SuppressLint("NewApi") 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); Log.d("registration Id", regid+""); 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); } // Send an upstream message. public void onClick(final View view) { if (view == findViewById(R.id.send)) { new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { String msg = ""; try { Bundle data = new Bundle(); data.putString("my_message", "Hello World"); data.putString("my_action", "com.google.android.gcm.demo.app.ECHO_NOW"); String id = Integer.toString(msgId.incrementAndGet()); gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data); msg = "Sent message"; } catch (IOException ex) { msg = "Error :" + ex.getMessage(); } return msg; } @Override protected void onPostExecute(String msg) { mDisplay.append(msg + "\n"); } }.execute(null, null, null); } else if (view == findViewById(R.id.clear)) { mDisplay.setText(""); } } @Override protected void onDestroy() { super.onDestroy(); } /** * @return Application 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 {@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 getSharedPreferences(DemoActivity.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() { // Your implementation here. } } 

GCMBroadCastReciver

 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); } } 

GCMIntentServicve

 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 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); } // Put the message into a notification and post it. // This is just one simple example of what you might choose to do with // a GCM message. private void sendNotification(String msg) { mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, DemoActivity.class), 0); Log.d("Notification Message==", msg); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_stat_gcm) .setContentTitle("Iween Notification") .setStyle(new NotificationCompat.BigTextStyle() .bigText(msg)) .setContentText(msg); Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); mBuilder.setSound(notificationSound); mBuilder.setContentIntent(contentIntent); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } } 

Manifest.xml

 <?xml version="1.0" encoding="utf-8"?> <!-- - 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. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.newgcmproject" android:versionCode="1" android:versionName="1.0"> <!-- GCM requires Android SDK version 2.2 (API level 8) or above. --> <!-- The targetSdkVersion is optional, but it always a good practice to target higher versions. --> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16"/> <!-- GCM connects to Google Services. --> <uses-permission android:name="android.permission.INTERNET" /> <!-- GCM requires a Google account. --> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <!-- Keeps the processor from sleeping when a message is received. --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Creates a custom permission so only this app can receive its messages. NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE, where PACKAGE is the application package name. --> <permission android:name="com.example.newgcmproject.permission.C2D_MESSAGE" android:protectionLevel="signature" /> <uses-permission android:name="com.example.newgcmproject.permission.C2D_MESSAGE" /> <!-- This app has permission to register and receive data message. --> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <!-- Main activity. --> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".DemoActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- WakefulBroadcastReceiver that will receive intents from GCM services and hand them to the custom IntentService. The com.google.android.c2dm.permission.SEND permission is necessary so only GCM services can send data messages for the app. --> <receiver android:name=".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="com.google.android.gcm.demo.app" /> </intent-filter> </receiver> <service android:name=".GcmIntentService" /> </application> </manifest> 

I do not receive any notifications on my device, even if I receive a message identifier when sending from the server side.

Edit Now I have made some changes to my code. I get an exception that the service is unavailable

0
source share
2 answers

My understanding of the parameters added to the message is as follows:

TimeToLive is set to 30 seconds, how long it will be on the server before removal.

Delay_while_idle is set to true, so if the phone is locked or asleep, the GCM server does not try to deliver the message.

So, if you send a message and your phone does not wake up or unlock within 30 seconds, you will never receive this message.

While you are developing the application, I would remove both of these arguments so that they default to 4 weeks and false. When you have determined that messages go through, you can experiment with different values ​​for them.

In the manifest, I believe the recipient category is incorrect. It should not be

  <category android:name="com.avilyne.android.gcmclient" /> 

It should match the name of the top-level package:

 package="com.example.gcmttestproject" 
+3
source

If I understand correctly that you want to display a notification on the device, open it when you click it. To do this, you can use the following code (replace MyActivity with your own for the intent):

 //Issues a notification to inform the user that server has sent a message. private static void generateNotification(Context context, String message, String title,) { int icon = R.drawable.logo; NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Intent notificationIntent = new Intent(context, MyActivity.class); // set intent so it does not start a new activity notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0); Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); Notification notification = new NotificationCompat.Builder(context) .setContentTitle(title) .setContentText(message) .setContentIntent(intent) .setSmallIcon(icon) .setLights(Color.YELLOW, 1, 2) .setAutoCancel(true) .setSound(defaultSound) .build(); notificationManager.notify(0, notification); 

}

This can be called using the onMessage() method on the GCMBaseIntentService .

0
source

All Articles