Я просмотрел все сообщения об ошибках "Not Registered" и не смог решить проблему.Я также связался со службой поддержки Firebase, к сожалению, я получил от них только URL-адреса официальной документации.
Наше приложение находилось в магазине некоторое время и успешно использовало GCM для уведомлений, когда приложение находится в фоновом режиме.Из-за устаревшего GCM мы сейчас пытаемся перейти на FCM.
Подведем итог: мы прошли шаги официальная миграция , изменили код в клиенте Android, обновили консоль Firebase, загрузили /добавлен google-services.json
, а также адаптирован URL-адрес конечной точки на сервере приложений.
Теперь проблема, с которой мы сталкиваемся, заключается в следующем: приложение запрашивает токен с помощью FirebaseInstanceId
singleton и успешно его получает.Этот токен мы затем отправляем на наш сервер приложений, который сохраняет его в БД.Затем сервер хочет отправить устройству Android сообщение с использованием метода Sender.sender(...)
, но получает печально известную ошибку «NotRegistered».Все это происходит в течение 10 секунд.
Мы попытали счастья на этих устройствах:
- Эмулятор устройства Nexus 5X API 27 x86
- Nexus 5X API 23
- Pixel 2 API 28
Глядя на список причин, по которым возвращается ошибка NotRegistered, я могу прокомментировать следующее:
- Клиентское приложение отменяет регистрацию в FCM -> смы контролируем телефон. Я могу исключить этот пункт
- Удаление приложения -> то же самое здесь
- Срок действия регистрационного токена истекает -> возможно, но в течение 10 секунд?
- "Если клиентское приложение обновлено, но новая версия не настроена на получение сообщений "-> что это значит?Поскольку приложение могло получать сообщения раньше, я думаю, оно настроено на их получение.
Android-клиент
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>
Код в Деятельности (сокращенно)
String token = FirebaseInstanceId.getInstance().getToken();
sendTokenToServer(token);
FirebaseMessaging.getInstance().subscribeToTopic("news");
Услуги
public class MyGcmListenerService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage message) {
...// never called
}
}
Я знаю, чтоFirebaseInstanceIdService
устарело, но я попробовал это также с новой версией, которая также не работает.
public class MyInstanceIDListenerService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
// never called...
String token = FirebaseInstanceId.getInstance().getToken();
sendTokenToServer(token);
}
}
Клиент Android использует следующие зависимости:
implementation "com.google.firebase:firebase-core:16.0.7"
implementation "com.google.firebase:firebase-messaging:17.4.0"
Сервер приложений
На стороне сервера мы используем следующую библиотеку.Согласно документации и этому сообщению мы должны иметь возможность использовать ту же библиотеку только с адаптированным URL-адресом конечной точки (https://fcm.googleapis.com/fcm/send) без каких-либо дальнейших изменений:
com.google.gcm:gcm-server:1.0.0
Уведомлениепостроен следующим образом:
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();
}
и отправлен с помощью этого вызова:
Result result = sender.send(message, deviceToken, retryCount);
if (result.getMessageId() == null) {
if (ERROR_CODE_NOT_REGISTERED.equals(result.getErrorCodeName())) { // <-- returns NotRegistered
// omitted
}
}
Консоль Firebase
Я загрузил отладку и выпустил SHA1sЯ также попытался отправить сообщение из консоли Firebase (Grow> Cloud Messaging> Уведомления), но на Android все еще нет сообщений.
Интересно, что у нас нет проблем с версией приложения для iOS, который также использует FCM. Сообщения с сервера приложений и с консоли Firebase приходят успешно. Однако приложение iOS никогда не использовало GCM.
Никаких подсказок? Что мы забыли? И спасибо, что прочитали здесь!