title: Not Registered error on server, FCM messages not received on Android
body: <p>I went through all the "Not Registered" error posts and could not solve the problem. I also contacted firebase support, unfortunately I only received URLs to the official documentation from them.</p>
  
  <p>Our app has been in the store for a while and was using GCM successfully for notifications when the app is in the background. Due to deprecation of GCM we are currently trying to migrate to FCM.</p>
  
  <p>Summarised:  We went through the <a href="https://developers.google.com/cloud-messaging/android/android-migrate-fcm" rel="nofollow noreferrer">official migration</a> steps, changed the code in the android client, updated firebase console, downloaded/added <code>google-services.json</code> and also adapted the endpoint URL on the app server.</p>
  
  <p>Now the problem we are facing is as follows:
  The app requests a token using <code>FirebaseInstanceId</code> singleton and receives it successfully. This token we then forward to our app server that saves it in a DB. Then, the server wants to send the android device a message using the <code>Sender.sender(...)</code> method but receives the infamous 'NotRegistered' error. All of this happens within about 10 seconds. </p>
  
  <p>We tried our luck on these devices:</p>
  
  <ul>
  <li>Emulator device Nexus 5X API 27 x86</li>
  <li>Nexus 5X API 23</li>
  <li>Pixel 2 API 28</li>
  </ul>
  
  <p>Looking at the <a href="https://firebase.google.com/docs/cloud-messaging/http-server-ref#error-codes" rel="nofollow noreferrer">list</a> of reasons the NotRegistered error is returned, I can comment as follows:</p>
  
  <ol>
  <li>Client app unregisters with FCM -> since we are in control of the phone I can exclude this point</li>
  <li>Uninstallation of app -> same here</li>
  <li>Registration token expires -> possible, but within 10 seconds?</li>
  <li>"If the client app is updated but the new version is not configured to receive messages" -> what does that exactly mean? Since the app was able to receive messages before, I guess it is configured to receive them.</li>
  </ol>
  
  <p><strong>Android Client</strong></p>
  
  <p><em>AndroidManifest.xml</em></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="com.acme.app"&gt;
  
      &lt;!-- permissions omitted for brevity --&gt;
  
      &lt;application
          android:name=".App"
          android:allowBackup="false"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:largeHeap="true"
          android:theme="@style/AppTheme"
          tools:node="replace"&gt;
  
          &lt;!-- Register AnalyticsReceiver and AnalyticsService to support background dispatching for Google Analytics on non-Google Play devices. --&gt;
          &lt;receiver
              android:name="com.google.android.gms.analytics.AnalyticsReceiver"
              android:enabled="true"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH" /&gt;
              &lt;/intent-filter&gt;
          &lt;/receiver&gt;
  
          &lt;service
              android:name="com.google.android.gms.analytics.AnalyticsService"
              android:enabled="true"
              android:exported="false" /&gt;
  
          &lt;service
              android:name=".gcm.MyGcmListenerService"
              android:exported="true"
              android:enabled="true"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.firebase.MESSAGING_EVENT" /&gt;                
              &lt;/intent-filter&gt;
          &lt;/service&gt;
          &lt;service android:name=".gcm.MyInstanceIDListenerService"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.google.firebase.INSTANCE_ID_EVENT" /&gt;
              &lt;/intent-filter&gt;
          &lt;/service&gt;
          &lt;!-- this is need for the firebase messaging service. It should be included automatically, but somehow gets deleted by the AndroidManifest file merging. So we manually have to add it --&gt;
          &lt;service android:name="com.google.firebase.components.ComponentDiscoveryService"&gt;
              &lt;meta-data
                  android:name="com.google.firebase.components:com.google.firebase.iid.Registrar"
                  android:value="com.google.firebase.components.ComponentRegistrar" /&gt;
          &lt;/service&gt;
  
          &lt;!-- omitted for brevity --&gt;
  
          &lt;meta-data
              android:name="com.google.android.gms.version"
              android:value="@integer/google_play_services_version" /&gt;        
          &lt;meta-data
              android:name="com.google.firebase.messaging.default_notification_icon"
              android:resource="@drawable/notification_icon" /&gt;        
          &lt;meta-data
              android:name="com.google.firebase.messaging.default_notification_color"
              android:resource="@color/base_color" /&gt;
          &lt;meta-data
              android:name="com.google.firebase.messaging.default_notification_channel_id"
              android:value="@string/default_notification_channel_id" /&gt;
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p><em>Code in Activity (shortened)</em></p>
  
  <pre><code>String token = FirebaseInstanceId.getInstance().getToken();
  sendTokenToServer(token);
  FirebaseMessaging.getInstance().subscribeToTopic("news");
  </code></pre>
  
  <p><em>Services</em></p>
  
  <pre><code>public class MyGcmListenerService extends FirebaseMessagingService {
  
      @Override
      public void onMessageReceived(RemoteMessage message) {
          ...// never called
      }
  }
  </code></pre>
  
  <p>I know that <code>FirebaseInstanceIdService</code> is deprecated, but I tried it also with the new version which also doesn't work.</p>
  
  <pre><code>public class MyInstanceIDListenerService extends FirebaseInstanceIdService {
      @Override
      public void onTokenRefresh() {
          // never called...
          String token = FirebaseInstanceId.getInstance().getToken();
          sendTokenToServer(token);
      }
  }
  </code></pre>
  
  <p>The android client uses the following dependencies:</p>
  
  <pre><code>    implementation "com.google.firebase:firebase-core:16.0.7"
      implementation "com.google.firebase:firebase-messaging:17.4.0"
  </code></pre>
  
  <p><strong>App Server</strong></p>
  
  <p>On the server side we are using the following library. According to the documentation and this <a href="https://stackoverflow.com/questions/42337383/pushnotification-server-side-implementation/42337465#42337465">post</a> we should be able to use the same library just with the adapted endpoint URL (<a href="https://fcm.googleapis.com/fcm/send" rel="nofollow noreferrer">https://fcm.googleapis.com/fcm/send</a>) without any further changes:</p>
  
  <pre><code>com.google.gcm:gcm-server:1.0.0 
  </code></pre>
  
  <p>Notification is built as follows:</p>
  
  <pre><code>private Message buildMessage(String title, String body, Map&lt;String, String&gt; attributes) {
      final Notification.Builder notificationBuilder = new Notification.Builder(null)
              .body(body)
              .title(StringUtils.trimToNull(title));
      final Message.Builder messageBuilder = new Message.Builder()
              .addData(KEY_BODY, body)
              .notification(notificationBuilder.build());
  
      if (!Strings.isNullOrEmpty(title)) {
          messageBuilder.addData(KEY_TITLE, title);
      }
  
      for (Map.Entry&lt;String, String&gt; attr : attributes.entrySet()) {
          messageBuilder.addData(attr.getKey(), attr.getValue());
      }
      return messageBuilder.build();
  }
  </code></pre>
  
  <p>and sent using this call:</p>
  
  <pre><code>Result result = sender.send(message, deviceToken, retryCount);
  
  if (result.getMessageId() == null) {
      if (ERROR_CODE_NOT_REGISTERED.equals(result.getErrorCodeName())) { // &lt;-- returns NotRegistered
          // omitted
      } 
  }
  </code></pre>
  
  <p><strong>Firebase console</strong></p>
  
  <p>I uploaded the debug and release SHA1s of the app. I also tried sending a message from the firebase console (Grow > Cloud messaging > Notifications), still no messages on Android.</p>
  
  <p>Interestingly, we do not have any problems with the iOS version of the app, which also uses FCM. Messages from the app server and from firebase console arrive successfully. However, the iOS app never used GCM.</p>
  
  <p>Any clues? What did we forget? And thanks for reading up to here!</p>