title: GCM Console shows 0 (zero) requests after a successful
body: <p>From my ASP.NET web service and using my GCM Browser API key I can successfully send a GCM Push Notification getting the following success response:</p>
  
  <p>{"multicast_id":4623804699821154941,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1393876717064721%59cd098ff9fd7ecd"}</p>
  
  <p>Two Problems:</p>
  
  <p>1) The Google Developers Console shows 0 (zero) Requests and 0 Errors even after multiple 'Sends' and browser refreshes of the console page. Shouldn't the count change with every GCM Push Notification?</p>
  
  <p>2) My Android device did not receive the push notification.</p>
  
  <p>My code is modeled after: 
  <a href="https://stackoverflow.com/questions/20407296/remote-server-returned-an-error-401-unathorized-in-c-sharp-gcm-response">remote server returned an error: (401) unathorized in C# GCM response</a></p>
  
  <p>The passed in Android device ID was copied from a successful Android device registration.
  My Server (web-service) code is below:</p>
  
  <pre><code>    using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Web;
      using System.Net;
      using System.Text;
      using System.IO;
      using System.Security.Cryptography.X509Certificates;
      using System.Net.Security;
      using System.Collections.Specialized;
  
      public class AndroidGCMPushNotification
      {
          public AndroidGCMPushNotification()
          {
              //
              // TODO: Add constructor logic here
              //
          }
          public string SendNotification(string deviceId, string message)
          {
              string BrowserAPIKey = "xxxxxxxxxxxxxxxxxxxxxxxxx";     // GCM Browser Key
  
              string tickerText = "ticker test GCM";
              string contentTitle = "content title GCM";
              string postData = "{ \"registration_ids\": [ \"" + deviceId + "\" ], \"data\": {\"tickerText\":\"" + tickerText + "\", \"contentTitle\":\"" + contentTitle + "\", \"message\": \"" + message + "\"}}";
  
      string sResponseFromServer = SendGCMNotification(BrowserAPIKey, postData);
      return sResponseFromServer;
  }
  
  private string SendGCMNotification(string apiKey, string postData, string postDataContentType = "application/json")
  {
      String sResponseFromServer = "";
      // from here:
      // https://stackoverflow.com/questions/11431261/unauthorized-when-calling-google-gcm
      //
      // original:
      // http://www.codeproject.com/Articles/339162/Android-push-notification-implementation-using-ASP
  
      ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
  
      //
      //  MESSAGE CONTENT
      byte[] byteArray = Encoding.UTF8.GetBytes(postData);
  
      //
      //  CREATE REQUEST
      HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
  
      Request.Method = "POST";
      Request.KeepAlive = false;
      Request.ContentType = postDataContentType;
      //Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
      Request.Headers.Add(HttpRequestHeader.Authorization, String.Format("key={0}", apiKey));
      Request.ContentLength = byteArray.Length;
  
      //Stream dataStream;
      try
      {
          Stream dataStream = Request.GetRequestStream();
  
          dataStream.Write(byteArray, 0, byteArray.Length);
          dataStream.Close();
      }
      catch (Exception e)
      {
          sResponseFromServer = e.Message;
      }
  
      //
      //  SEND MESSAGE
      try
      {
          WebResponse Response = Request.GetResponse();
  
          HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
  
          if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
          {
              sResponseFromServer = "Unauthorized - need new token";
  
          }
          else if (!ResponseCode.Equals(HttpStatusCode.OK))
          {
              sResponseFromServer = "Response from web service isn't OK";
          }
  
          StreamReader Reader = new StreamReader(Response.GetResponseStream());
          sResponseFromServer = Reader.ReadToEnd();
          Reader.Close();
      }
      catch (Exception e)
      {
          sResponseFromServer = e.Message;
      }
      return sResponseFromServer;
  }
  
  public static bool ValidateServerCertificate(
                                            object sender,
                                            X509Certificate certificate,
                                            X509Chain chain,
                                            SslPolicyErrors sslPolicyErrors)
  {
      return true;
  }
  </code></pre>
  
  <p>}</p>
  
  <p>On the Android client side I have the following notification-receive code:</p>
  
  <pre><code>package com.MichaelResslerFineArt.eclipmessenger;
  
  import java.io.IOException;
  import java.util.concurrent.atomic.AtomicInteger;
  
  import com.MichaelResslerFineArt.eclipmessenger.ProfileActivity;
  import com.MichaelResslerFineArt.eclipmessenger.R;
  import com.MichaelResslerFineArt.eclipmessenger.ProfileActivity.GcmBroadcastReceiver;
  import com.MichaelResslerFineArt.eclipmessenger.ProfileActivity.GcmIntentService;
  import com.google.android.gms.common.ConnectionResult;
  import com.google.android.gms.common.GooglePlayServicesUtil;
  import com.google.android.gms.gcm.GoogleCloudMessaging;
  
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.os.SystemClock;
  import android.app.Activity;
  import android.app.IntentService;
  import android.app.NotificationManager;
  import android.app.PendingIntent;
  import android.content.ComponentName;
  
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.content.pm.PackageInfo;
  import android.content.pm.PackageManager.NameNotFoundException;
  import android.support.v4.app.NotificationCompat;
  import android.support.v4.content.WakefulBroadcastReceiver;
  import android.util.Log;
  import android.view.Menu;
  import android.view.View;
  import android.widget.Toast;
  
  public class ProfileActivity 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 final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
  
      String SENDER_ID = "594966827111";    // GCM Project Number
  
  
      public static final String LOG_MSG_TAG = "eClipMessenger";
      GoogleCloudMessaging gcm;
      AtomicInteger msgId = new AtomicInteger();
      SharedPreferences prefs;
      Context context;
  
      String regid;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_profile);
  
          context = getApplicationContext();
  
          // Check device for Play Services APK.
          GcmApi gcmApi = new GcmApi();
          if (gcmApi.checkPlayServices(this)) {
              // If this check succeeds, proceed with normal processing.
              // Otherwise, prompt user to get valid Play Services APK.
              Toast.makeText(this, "Success checking APK.", Toast.LENGTH_LONG).show();
              Log.i(LOG_MSG_TAG, "Success checking APK.");
  
              gcm = GoogleCloudMessaging.getInstance(this);
              regid = getRegistrationId(context);
  
              if (regid.isEmpty()) {
                  registerInBackground();
              }
              else {
                  Log.i(LOG_MSG_TAG, "GCM Reg ID: " + regid);
              }
          } else {
              Log.i(LOG_MSG_TAG, "No valid Google Play Services APK found.");
          }
      }
  
      // You need to do the Play Services APK check here too.
      @Override
      protected void onResume() {
          super.onResume();
          GcmApi gcmApi = new GcmApi();
          gcmApi.checkPlayServices(this);
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.profile, menu);
          return true;
      }
  
      /**
       * Gets the current registration ID for application on GCM service.
       * &lt;p&gt;
       * 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 = getGCMPreferences(context);
          String registrationId = prefs.getString(PROPERTY_REG_ID, "");
          if (registrationId.isEmpty()) {
              Log.i(LOG_MSG_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(LOG_MSG_TAG, "App version changed.");
              return "";
          }
          return registrationId;
      }
  
      /**
       * @return Application's {@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(ProfileActivity.class.getSimpleName(),
                  Context.MODE_PRIVATE);
      }
  
      /**
       * @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 (NameNotFoundException e) {
              // should never happen
              throw new RuntimeException("Could not get package name: " + e);
          }
      }
  
      /**
       * Registers the application with GCM servers asynchronously.
       * &lt;p&gt;
       * Stores the registration ID and app versionCode in the application's
       * shared preferences.
       */
      private void registerInBackground() {
          new AsyncTask&lt;Void, Void, String&gt;() {
              @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) {
                  Log.i(LOG_MSG_TAG, 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.
      }       
      /**
       * Stores the registration ID and app versionCode in the application's
       * {@code SharedPreferences}.
       *
       * @param context application's context.
       * @param regId registration ID
       */
      private void storeRegistrationId(Context context, String regId) {
          Log.i(LOG_MSG_TAG, "entered storeRegistrationId()");
          final SharedPreferences prefs = getGCMPreferences(context);
          Log.i(LOG_MSG_TAG, "retrieved preferences");
          int appVersion = getAppVersion(context);
          Log.i(LOG_MSG_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();
      }       
  
      /*
      public void sendGcm(final View view) {
          if (view == findViewById(R.id.button2)) {
              new AsyncTask&lt;Void, Void, String&gt;() {
                  @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) {
                      Log.i(LOG_MSG_TAG, msg);
                      //mDisplay.append(msg + "\n");
                  }
              }.execute(null, null, null);
  //        } else if (view == findViewById(R.id.textView2)) {
  //            mDisplay.setText("");
          }
      }
      */
      public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
              Log.i(LOG_MSG_TAG, "onReceive");
  
              // 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);
          }
      }
      public class GcmIntentService extends IntentService {
          public static final int NOTIFICATION_ID = 1;
          private NotificationManager mNotificationManager;
          NotificationCompat.Builder builder;
  
          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.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's 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&lt;5; i++) {
                          Log.i(LOG_MSG_TAG, "Working... " + (i+1)
                                  + "/5 @ " + SystemClock.elapsedRealtime());
                          try {
                              Thread.sleep(5000);
                          } catch (InterruptedException e) {
                          }
                      }
                      Log.i(LOG_MSG_TAG, "Completed work @ " + SystemClock.elapsedRealtime());
                      // Post notification of received message.
                      sendNotification("Received: " + extras.toString());
                      Log.i(LOG_MSG_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) {
              Log.i(LOG_MSG_TAG, "sendNotification");
  
              mNotificationManager = (NotificationManager)
                      this.getSystemService(Context.NOTIFICATION_SERVICE);
  
              PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                      new Intent(this, ProfileActivity.class), 0);
  
              NotificationCompat.Builder mBuilder =
                      new NotificationCompat.Builder(this)
              .setSmallIcon(R.drawable.ic_launcher)
              .setContentTitle("GCM Notification")
              .setStyle(new NotificationCompat.BigTextStyle()
              .bigText(msg))
              .setContentText(msg);
  
              mBuilder.setContentIntent(contentIntent);
              mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
          }
      }
  }
  </code></pre>
  
  <p>And this separate class for checking the Play Services:</p>
  
  <pre><code>package com.MichaelResslerFineArt.eclipmessenger;
  
  import android.app.Activity;
  import android.util.Log;
  import android.widget.Toast;
  
  import com.google.android.gms.common.ConnectionResult;
  import com.google.android.gms.common.GooglePlayServicesUtil;
  
  public class GcmApi {
  
      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 final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
  
      String SENDER_ID = "594966827111";    // GCM Project Number
  
      /**
       * 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's system settings.
       */
      public boolean checkPlayServices(ProfileActivity currActivity) {
          int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(currActivity);
          if (resultCode != ConnectionResult.SUCCESS) {
              if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                  GooglePlayServicesUtil.getErrorDialog(resultCode, currActivity,
                          PLAY_SERVICES_RESOLUTION_REQUEST).show();
              } else {
                  Log.i(ProfileActivity.LOG_MSG_TAG, "This device is not supported.");
                  Toast.makeText(currActivity, "This device is not supported.", Toast.LENGTH_LONG).show();
                  currActivity.finish();
              }
              return false;
          }
          return true;
      }
  }
  </code></pre>
  
  <p>And the Android client side manifest:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.MichaelResslerFineArt.eclipmessenger"
  android:versionCode="1"
  android:versionName="1.0" &gt;
  
  &lt;uses-sdk
      android:minSdkVersion="10"
      android:targetSdkVersion="18" /&gt;
  &lt;uses-permission android:name="android.permission.INTERNET"/&gt;
  &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/&gt;
  &lt;uses-permission android:name="android.permission.GET_ACCOUNTS"/&gt;
  &lt;uses-permission android:name="android.permission.WAKE_LOCK"/&gt;
  &lt;permission     android:name="com.MichaelResslerFineArt.eclipmessenger.permission.C2D_MESSAGE"
      android:protectionLevel="signature" /&gt;
  &lt;uses-permission     android:name="com.MichaelResslerFineArt.eclipmessenger.permission.C2D_MESSAGE" /&gt;            
  
  &lt;application
      android:allowBackup="true"
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name"
      android:theme="@style/AppTheme" &gt;
      &lt;activity
          android:name="com.MichaelResslerFineArt.eclipmessenger.ProfileActivity"
          android:label="@string/app_name" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MAIN" /&gt;
  
              &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  
      &lt;meta-data android:name="com.google.android.gms.version"
                 android:value="@integer/google_play_services_version" /&gt;
      &lt;receiver
          android:name=".GcmBroadcastReceiver"
          android:permission="com.google.android.c2dm.permission.SEND" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="com.google.android.c2dm.intent.RECEIVE" /&gt;
              &lt;category android:name="com.MichaelResslerFineArt.eclipmessenger" /&gt;
          &lt;/intent-filter&gt;
      &lt;/receiver&gt;
      &lt;service android:name=".GcmIntentService" /&gt;
  
  &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>