title: GCM is not working
body: <p>I decided to implement Google Cloud Messaging push notifications to notify users about news. I think it is topic messaging. For implement I took the <a href="https://github.com/googlesamples/google-services/tree/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart" rel="nofollow">Google GCM sample</a>. I added all needed services, permissions and receiver in manifest. When I send a post request to Google GCM server, the response is true with message ID, but device doesn't notify. What is the matter? I tested in Bluestacks.</p>
  
  <p>My manifest:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      package="packagename" &gt;
  
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
      &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
      &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /&gt;
      &lt;uses-permission android:name="packagename.permission.C2D_MESSAGE" /&gt;
  
      &lt;permission android:name="packagename.permission.C2D_MESSAGE"
          android:protectionLevel="signature" /&gt;
  
      &lt;application
          android:name=".App"
          android:allowBackup="true"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" &gt;
          &lt;activity
              android:name=".activities.MainActivity"
              android:configChanges="keyboardHidden|orientation|screenSize"
              android:label="@string/app_name"
              android:launchMode="singleTop" &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;activity
              android:name=".activities.BiographyActivity"
              android:configChanges="keyboardHidden|orientation|screenSize"
              android:label="@string/title_biography"
              android:parentActivityName=".activities.MainActivity"
              tools:ignore="UnusedAttribute" &gt;
              &lt;meta-data
                  android:name="android.support.PARENT_ACTIVITY"
                  android:value=".activities.MainActivity" /&gt;
          &lt;/activity&gt;
          &lt;activity
              android:name=".activities.AboutActivity"
              android:label="@string/title_about_app" &gt;
              &lt;meta-data
                  android:name="android.support.PARENT_ACTIVITY"
                  android:value=".activities.MainActivity" /&gt;
          &lt;/activity&gt;
          &lt;activity android:name=".activities.CrashReportDialog"
              android:theme="@style/Theme.Dialog"
              android:process=":error_report"
              android:launchMode="singleInstance"
              android:excludeFromRecents="true"
              android:finishOnTaskLaunch="true" /&gt;
  
          &lt;meta-data
              android:name="com.google.android.gms.version"
              android:value="@integer/google_play_services_version" /&gt;
  
          &lt;receiver
              android:name="com.google.android.gms.gcm.GcmReceiver"
              android:exported="true"
              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;action android:name="com.google.android.c2dm.intent.REGISTRATION" /&gt;
                  &lt;category android:name="packagename" /&gt;
              &lt;/intent-filter&gt;
          &lt;/receiver&gt;
          &lt;service
              android:name="packagename.AppGcmListenerService"
              android:exported="false" &gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.android.c2dm.intent.RECEIVE" /&gt;
              &lt;/intent-filter&gt;
          &lt;/service&gt;
          &lt;service
              android:name="packagename.AppInstanceIDListenerService"
              android:exported="false"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.android.gms.iid.InstanceID"/&gt;
              &lt;/intent-filter&gt;
          &lt;/service&gt;
          &lt;service
              android:name="packagename.RegistrationIntentService"
              android:exported="false"&gt;
          &lt;/service&gt;
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p>Main Activity:</p>
  
  <pre><code>public class MainActivity extends AppCompatActivity {    
  
      private BroadcastReceiver mRegistrationBroadcastReceiver;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          mRegistrationBroadcastReceiver = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                  SharedPreferences sharedPreferences =
                          PreferenceManager.getDefaultSharedPreferences(context);
                  boolean sentToken = sharedPreferences
                          .getBoolean(GcmPreferences.SENT_TOKEN_TO_SERVER, false);
                  if (sentToken) {
                      Log.i("GCM", "Success!");
                  } else {
                      Log.i("GCM", "Error!");
                  }
              }
          };
  
          Intent intent = new Intent(this, RegistrationIntentService.class);
          startService(intent);
      }
  }
  </code></pre>
  
  <p>GCM Listener Service:</p>
  
  <pre><code>public class AppGcmListenerService extends GcmListenerService {
  
      private static final String TAG = "GCM";
  
      /**
       * Called when message is received.
       *
       * @param from SenderID of the sender.
       * @param data Data bundle containing message data as key/value pairs.
       *             For Set of keys use data.keySet().
       */
      @Override
      public void onMessageReceived(String from, Bundle data) {
          String message = data.getString("message");
          Log.d(TAG, "From: " + from);
          Log.d(TAG, "Message: " + message);
  
          /**
           * Production applications would usually process the message here.
           * Eg: - Syncing with server.
           *     - Store message in local database.
           *     - Update UI.
           */
  
          /**
           * In some cases it may be useful to show a notification indicating to the user
           * that a message was received.
           */
          sendNotification(message);
      }
  
      /**
       * Create and show a simple notification containing the received GCM message.
       *
       * @param message GCM message received.
       */
      private void sendNotification(String message) {
          Intent intent = new Intent(this, MainActivity.class);
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                  PendingIntent.FLAG_ONE_SHOT);
  
          Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
          NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                  .setSmallIcon(R.drawable.ic_app)
                  .setContentTitle("GCM Message")
                  .setContentText(message)
                  .setAutoCancel(true)
                  .setSound(defaultSoundUri)
                  .setContentIntent(pendingIntent);
  
          NotificationManager notificationManager =
                  (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  
          notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
      }
  }
  </code></pre>
  
  <p>Instance ID Listener Service:</p>
  
  <pre><code>public class AppInstanceIDListenerService extends InstanceIDListenerService {
  
      /**
       * Called if InstanceID token is updated. This may occur if the security of
       * the previous token had been compromised. This call is initiated by the
       * InstanceID provider.
       */
      @Override
      public void onTokenRefresh() {
          // Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
          Intent intent = new Intent(this, RegistrationIntentService.class);
          startService(intent);
      }
  }
  </code></pre>
  
  <p>Registration Intent Service:</p>
  
  <pre><code>public class RegistrationIntentService extends IntentService {
  
  private static final String TAG = "GCM";
  
  public RegistrationIntentService() {
      super(TAG);
  }
  
  @Override
  protected void onHandleIntent(Intent intent) {
      SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
  
      try {
          // In the (unlikely) event that multiple refresh operations occur simultaneously,
          // ensure that they are processed sequentially.
          synchronized (TAG) {
              // Initially this call goes out to the network to retrieve the token, subsequent calls
              // are local.
              InstanceID instanceID = InstanceID.getInstance(this);
              String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
                      GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
  
              Log.d(TAG, "GCM Registration Token: " + token);
  
              subscribeTopics(token);
  
              // You should store a boolean that indicates whether the generated token has been
              // sent to your server. If the boolean is false, send the token to your server,
              // otherwise your server should have already received the token.
              sharedPreferences.edit().putBoolean(GcmPreferences.SENT_TOKEN_TO_SERVER, true).apply();
          }
      } catch (Exception e) {
          Log.d(TAG, "Failed to complete token refresh", e);
          // If an exception happens while fetching the new token or updating our registration data
          // on a third-party server, this ensures that we'll attempt the update at a later time.
          sharedPreferences.edit().putBoolean(GcmPreferences.SENT_TOKEN_TO_SERVER, false).apply();
      }
      // Notify UI that registration has completed, so the progress indicator can be hidden.
      Intent registrationComplete = new Intent(GcmPreferences.REGISTRATION_COMPLETE);
      LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
  }
  
  /**
   * Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
   *
   * @param token GCM token
   * @throws IOException if unable to reach the GCM PubSub service
   */
  private void subscribeTopics(String token) throws IOException {
      GcmPubSub.getInstance(this).subscribe(token, "/topics/global", null);
  }
  </code></pre>
  
  <p>}</p>
  
  <p>My PHP POST request:</p>
  
  <pre><code>&lt;?php
  $postData = array('to' =&gt; '/topics/global',
                    'notification' =&gt; array(
                        'body' =&gt; 'GCM Topic Message',
                        'title' =&gt; 'Test message'));
  
  $curl = curl_init('https://gcm-http.googleapis.com/gcm/send');
  
  curl_setopt_array($curl, array(CURLOPT_POST =&gt; true,
  CURLOPT_RETURNTRANSFER =&gt; true,
  CURLOPT_HTTPHEADER =&gt; array(
      'Authorization:key=AIzaSyBbUfgnuDyAmO9G8wk6_eqwZFiYX0J0PxI',
      'Content-Type:application/json'
  ),
  CURLOPT_POSTFIELDS =&gt; json_encode($postData)));
  
  $response = curl_exec($curl);
  
  if($response === false){
      die(curl_error($curl));
  }
  
  $responseData = json_decode($response, true);
  
  // Print the date from the response
  print_r($responseData);
  ?&gt;
  </code></pre>
  
  <p>I tested POST request. Android app tested on <a href="http://bluestacks.com" rel="nofollow">Bluestacks App Player</a> and real phone.</p>