Подтвердить что ты не робот

Как исправить ошибку регистрации Google Cloud Messaging: SERVICE_NOT_AVAILABLE?

У меня возникла странная проблема: я давно использую GCM в своем приложении, и все работает отлично. Однако перед выпуском в Google Play я изменил имя своего приложения с com.android.testapp на com.android.recognition и после этого GCM перестала работать. Сначала я получил ошибку en GCM sender id not set on constructor и исправил ее, переопределив getSenderIds(Context context), но теперь я не могу получить идентификатор регистрации. Вот сообщения из logcat: enter image description here

Как я могу это исправить? Когда я переключился на новый пакет, я изменил все в файле манифеста на новый пакет:

<receiver
        android:name="com.google.android.gcm.GCMBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="com.android.recognition" />
        </intent-filter>
    </receiver>

Так в чем проблема? Может ли переименование пакета приложения вызвать это или есть другая причина?

4b9b3361

Ответ 1

В этой ошибке SERVICE_NOT_AVAILABLE указано, что GCM Service недоступен в текущем состоянии. Подождите и попробуйте через некоторое время.

Это происходит много раз (как и мой опыт), поэтому не беспокойтесь об этом.


См. класс GCMConstants GCM Lib.

/**
     * The device can't read the response, or there was a 500/503 from the
     * server that can be retried later. The application should use exponential
     * back off and retry.
     */
    public static final String ERROR_SERVICE_NOT_AVAILABLE =
            "SERVICE_NOT_AVAILABLE";

Более подробно см. handleRegistration() of GCMBaseIntentService

private void handleRegistration(final Context context, Intent intent) {
        String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID);
        String error = intent.getStringExtra(EXTRA_ERROR);
        String unregistered = intent.getStringExtra(EXTRA_UNREGISTERED);
        Log.d(TAG, "handleRegistration: registrationId = " + registrationId +
                ", error = " + error + ", unregistered = " + unregistered);

        // registration succeeded
        if (registrationId != null) {
            GCMRegistrar.resetBackoff(context);
            GCMRegistrar.setRegistrationId(context, registrationId);
            onRegistered(context, registrationId);
            return;
        }

        // unregistration succeeded
        if (unregistered != null) {
            // Remember we are unregistered
            GCMRegistrar.resetBackoff(context);
            String oldRegistrationId =
                    GCMRegistrar.clearRegistrationId(context);
            onUnregistered(context, oldRegistrationId);
            return;
        }

        // last operation (registration or unregistration) returned an error;
        Log.d(TAG, "Registration error: " + error);
        // Registration failed
        if (ERROR_SERVICE_NOT_AVAILABLE.equals(error)) {
            boolean retry = onRecoverableError(context, error);
            if (retry) {
                int backoffTimeMs = GCMRegistrar.getBackoff(context);
                int nextAttempt = backoffTimeMs / 2 +
                        sRandom.nextInt(backoffTimeMs);
                Log.d(TAG, "Scheduling registration retry, backoff = " +
                        nextAttempt + " (" + backoffTimeMs + ")");
                Intent retryIntent =
                        new Intent(INTENT_FROM_GCM_LIBRARY_RETRY);
                retryIntent.putExtra(EXTRA_TOKEN, TOKEN);
                PendingIntent retryPendingIntent = PendingIntent
                        .getBroadcast(context, 0, retryIntent, 0);
                AlarmManager am = (AlarmManager)
                        context.getSystemService(Context.ALARM_SERVICE);
                am.set(AlarmManager.ELAPSED_REALTIME,
                        SystemClock.elapsedRealtime() + nextAttempt,
                        retryPendingIntent);
                // Next retry should wait longer.
                if (backoffTimeMs < MAX_BACKOFF_MS) {
                  GCMRegistrar.setBackoff(context, backoffTimeMs * 2);
                }
            } else {
                Log.d(TAG, "Not retrying failed operation");
            }
        } else {
            // Unrecoverable error, notify app
            onError(context, error);
        }
    }

Ответ 2

На вопрос ответ, в моем случае это было немного сложнее.

  • Проверьте наличие активного интернет-соединения
  • Убедитесь, что у вас есть разрешение на использование Интернета в манифесте
  • Убедитесь, что имя пакета верное, как упоминал Эран
  • Время устройства настроено правильно. Даже если все будет идеально, оно не сработает, если часы устройства установлены неправильно.

Неправильные часы вызвали проблему для меня.:)

Ответ 3

Убедитесь, что вы изменили имя пакета в части разрешений манифеста:

<permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />

У меня была аналогичная ошибка из-за неправильного имени пакета в этой части.

Ответ 4

SERVICE_NOT_AVAILABLE - одна из самых неприятных проблем с облачными сообщениями Google. Это исключение, вызванное GoogleCloudMessaging.register(SENDER_ID), вызов функции, который регистрирует устройство для push-уведомлений и возвращает идентификатор регистрации.

  • SERVICE_NOT_AVAILABLE может означать, что пользовательское устройство не может прочитать ответ на запрос на регистрацию или код ошибки 500/503 был возвращен с сервера. Разработчики не имеют возможности исправить эту ошибку, потому что она заканчивается в Googles, поэтому мы можем вслепую предположить, что пользователь должен повторить попытку через несколько часов.
  • SERVICE_NOT_AVAILABLE может возникать на некоторых устройствах, даже если регистрация прошла успешно. Это можно устранить, применяя приемник широковещательной передачи, чтобы поймать токен при сбое вызова. Я применил это решение и, возможно, устранил проблему для некоторых пользователей, но все же я получил много других жалоб SERVICE_NOT_AVAILABLE.
  • SERVICE_NOT_AVAILABLE может произойти из-за устаревшей или отсутствующей библиотеки Google Play Services на устройстве. В этом случае приложение может теоретически уведомить пользователя об обновлении сервисов Google Play, открыв соответствующий список приложений Google Play. Тем не менее, приложение не знает, что именно поэтому SERVICE_NOT_AVAILABLE был брошен, поэтому он не может вслепую перенаправить пользователя на страницу приложения Google Play Services в Google Play.
  • SERVICE_NOT_AVAILABLE может возникать, когда часы устройств не синхронизируются с сетью. Опять же, разработчики не знают, что это точная проблема, поэтому мы можем вслепую предложить пользователю проверить синхронизацию их системных часов, надеясь, что они являются одними из немногих, чьи часы не синхронизированы.
  • SERVICE_NOT_AVAILABLE может произойти, когда корневой пользователь удалил приложение Hangouts/GTalk с их устройства (потому что они считали его вирусом). GCM реализуется и обрабатывается Hangouts/GTalk, поэтому использовать GCM без него невозможно.
  • SERVICE_NOT_AVAILABLE может возникнуть, если пользователь запускает устройство, на котором не установлены Google API (например, Amazon Kindle). Здесь нечего делать, эти пользователи никогда не получат push-уведомления из вашего приложения.

Подробнее: http://eladnava.com/google-cloud-messaging-extremely-unreliable/

Только этих вопросов было достаточно, чтобы заставить меня искать альтернативы GCM. Id получает 1-звездочный обзор в моем приложении каждый день или два, с комментарием, содержащим сообщение об ошибке, отображаемое при вызове SERVICE_NOT_AVAILABLE. Я ничего не мог сделать, чтобы помочь этим пользователям, потому что большинство из них получало их по причинам, не зависящим от них.

Альтернатива облачным сообщениям Google

Pushy (https://pushy.me/) является автономным шлюзом push-уведомлений, полностью независимым от GCM. Он поддерживает собственное фоновое сокетное соединение, как и GCM, для получения push-уведомлений. Основным протоколом является MQTT, чрезвычайно легкий протокол pub/sub, использующий очень небольшую пропускную способность сети и батарею.

Огромное преимущество Pushy заключается в том, что код для отправки push-уведомления (с сервера) и регистрации устройства для push-уведомлений фактически взаимозаменяем между GCM и Pushy. Это делает его очень простым переключиться на Pushy после внедрения GCM и вынудить его отключить для своей нестабильности.

(Полное раскрытие: я основал Pushy для своих собственных проектов и понял, что многие приложения выиграют от такой услуги)

Ответ 5

Для меня - время устройства было неправильным. Я изменил настройки устройства, чтобы использовать "Автоматическая дата и время", попробовал снова и все хорошо.

Приветствия

Ответ 6

У меня была такая же проблема, но ни одно из вышеперечисленных решений не решило проблему в моем случае. К счастью, я недавно решил это, и я хочу объяснить, как, прыгая, это поможет другим:

В моем случае я регистрировал услугу push в пользовательском классе приложения (который выполняется перед любой деятельностью, и я думаю, из-за этого некоторые вещи не были инициализированы должным образом). Изменение его на основное действие решило проблему.

public class MyCustomApp extends Application {

    @Override
    public void onCreate() {
         super.onCreate();
         PushService.register(this); //BAD IDEA, don't register pushes in Application Class
    }

}

Ответ 7

У меня была аналогичная проблема. Работал отлично на google nexus (Android 4.4.2), но не на галактике Samsung s3 (Android 4.1.2). Я получил SERVICE_NOT_AVAILABLE при регистрации на Samsung. Оказалось, что время на Samsung отключено. Он не был настроен на автоматическое обновление с помощью Network Time. Как только я решил, что GCM работает как шарм. Спасибо - Umesh

Ответ 8

Для меня была проблема подключения. Изменение интернет-соединения решило мою проблему

Ответ 9

Для меня я перешел на "Доступ к фоновым данным" для служб google, установив флажок "Ограничить исходные данные" в опции "Использование данных" на моем Galaxy S4. Как только я включил его, проблема была решена в сети подвалов. На Wifi он работал нормально.

Ответ 10

В моем случае решение заключалось в том, чтобы добавить манифест нового действия-фильтра-действия, РЕГИСТРАЦИЯ, за https://snowdog.co/blog/dealing-with-service_not_available-google-cloud-messaging/

    <receiver
        android:name=".RemoteNotificationReceiver"
        android:permission="com.getset.getset.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.getset.getset.c2dm.intent.RECEIVE" />
            <action android:name="com.getset.getset.c2dm.intent.REGISTRATION" />
            <category android:name="com.getset.getset" />
        </intent-filter>
    </receiver>

Я должен признать, что я удивлен, что это работает, учитывая, что он отсутствует в учебнике, но его вывод определенно превращает успешный идентификатор регистрации в исключение.

Примечание: использование эмулятора Nexus 5 API 21 (Lollipop).

Ответ 11

Для меня проблема заключалась в том, что телефон не был подключен к Интернету. Я отключился и подключился к Wi-Fi, а также протестировал соединение с браузером и протестировал его снова. Работали как шарм: -)

Ответ 12

Я включил "Доступ к фоновым данным" для служб google. Снимите флажок "Ограничить исходные данные" в опции "Использование данных". Это работает для меня!

Ответ 13

Для меня goolge заблокировал мой IP! Я должен был reset подключиться к DSL, чтобы получить новый IP-адрес из пула, и все снова сработало, idk, почему они заблокировали меня, возможно, для тестирования многих приложений? В любом случае, теперь я работаю, надеюсь, это поможет кому-то еще:)

Ответ 14

Для меня проблема SERVICE_NOT_AVAILABLE была в моем проекте приложения из-за класса приемника. Поэтому я решил решить эту проблему, как показано ниже. <receiver android:name="receiver name" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE"/> <action android:name="com.google.android.c2dm.intent.REGISTRATION"/> <category android:name="your package"/> </intent-filter> </receiver> Надеюсь, это поможет вам:-).

Ответ 15

После долгой борьбы мне удалось разобраться в этой проблеме. Убедитесь, что приложение Google Play Services обновлено и что его фоновая синхронизация не отключена на вашем телефоне.