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.
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.
Summarised: We went through the official migration steps, changed the code in the android client, updated firebase console, downloaded/added google-services.json and also adapted the endpoint URL on the app server.
Now the problem we are facing is as follows:
The app requests a token using FirebaseInstanceId 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 Sender.sender(...) method but receives the infamous 'NotRegistered' error. All of this happens within about 10 seconds.
We tried our luck on these devices:
- Emulator device Nexus 5X API 27 x86
- Nexus 5X API 23
- Pixel 2 API 28
Looking at the list of reasons the NotRegistered error is returned, I can comment as follows:
- Client app unregisters with FCM -> since we are in control of the phone I can exclude this point
- Uninstallation of app -> same here
- Registration token expires -> possible, but within 10 seconds?
- "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.
Android Client
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.acme.app">
<!-- permissions omitted for brevity -->
<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">
<!-- Register AnalyticsReceiver and AnalyticsService to support background dispatching for Google Analytics on non-Google Play devices. -->
<receiver
android:name="com.google.android.gms.analytics.AnalyticsReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.gms.analytics.ANALYTICS_DISPATCH" />
</intent-filter>
</receiver>
<service
android:name="com.google.android.gms.analytics.AnalyticsService"
android:enabled="true"
android:exported="false" />
<service
android:name=".gcm.MyGcmListenerService"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".gcm.MyInstanceIDListenerService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<!-- 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 -->
<service android:name="com.google.firebase.components.ComponentDiscoveryService">
<meta-data
android:name="com.google.firebase.components:com.google.firebase.iid.Registrar"
android:value="com.google.firebase.components.ComponentRegistrar" />
</service>
<!-- omitted for brevity -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/notification_icon" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/base_color" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
</application>
</manifest>
Code in Activity (shortened)
String token = FirebaseInstanceId.getInstance().getToken();
sendTokenToServer(token);
FirebaseMessaging.getInstance().subscribeToTopic("news");
Services
public class MyGcmListenerService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage message) {
...// never called
}
}
I know that FirebaseInstanceIdService is deprecated, but I tried it also with the new version which also doesn't work.
public class MyInstanceIDListenerService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
// never called...
String token = FirebaseInstanceId.getInstance().getToken();
sendTokenToServer(token);
}
}
The android client uses the following dependencies:
implementation "com.google.firebase:firebase-core:16.0.7"
implementation "com.google.firebase:firebase-messaging:17.4.0"
App Server
On the server side we are using the following library. According to the documentation and this post we should be able to use the same library just with the adapted endpoint URL (https://fcm.googleapis.com/fcm/send) without any further changes:
com.google.gcm:gcm-server:1.0.0
Notification is built as follows:
private Message buildMessage(String title, String body, Map<String, String> 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<String, String> attr : attributes.entrySet()) {
messageBuilder.addData(attr.getKey(), attr.getValue());
}
return messageBuilder.build();
}
and sent using this call:
Result result = sender.send(message, deviceToken, retryCount);
if (result.getMessageId() == null) {
if (ERROR_CODE_NOT_REGISTERED.equals(result.getErrorCodeName())) { // <-- returns NotRegistered
// omitted
}
}
Firebase console
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.
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.
Any clues? What did we forget? And thanks for reading up to here!