it-swarm.com.ru

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

Я столкнулся со странной проблемой - я давно использую GCM в своем приложении, и все работает отлично. Однако перед выпуском в Google Play я изменил имя пакета приложения с com.Android.testapp на com.Android.recognition и после этого GCM перестал работать. Сначала я получил ошибку 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>

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

24
MainstreamDeveloper00

Эта ошибка 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() из 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);
        }
    }
30
Pankaj Kumar

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

  1. Убедитесь, что у вас есть активное подключение к интернету
  2. Убедитесь, что у вас есть разрешение на Интернет в вашем манифесте
  3. Убедитесь, что имя пакета правильное, как упомянул Эран
  4. Время устройства правильно настроено. Даже если все идеально, оно не будет работать, если часы устройства установлены неправильно.

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

42
Aman Gautam

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

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

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

18
Eran

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

  1. SERVICE_NOT_AVAILABLE может означать, что пользовательское устройство не может прочитать ответ на запрос регистрации или код ошибки 500/503 был возвращен с сервера. Разработчики не могут исправить эту ошибку, потому что это на стороне Google, поэтому мы можем вслепую предложить пользователю повторить попытку через несколько часов.
  2. SERVICE_NOT_AVAILABLE может произойти на некоторых устройствах, даже если регистрация прошла успешно. Это можно исправить, внедрив обходной приемник широковещательной передачи, чтобы перехватить токен при сбое вызова. Я реализовал этот обходной путь, и он мог решить проблему для некоторых пользователей, но все же я получил много других жалоб SERVICE_NOT_AVAILABLE.
  3. SERVICE_NOT_AVAILABLE может произойти из-за устаревшей или отсутствующей библиотеки Google Play Services на устройстве. В этом случае приложение теоретически может уведомить пользователя об обновлении Сервисов Google Play, открыв соответствующий список приложений Google Play. Однако приложение не имеет ни малейшего представления о том, что именно поэтому было выброшено SERVICE_NOT_AVAILABLE, поэтому оно не может вслепую перенаправлять пользователя на страницу приложения служб Google Play в Google Play.
  4. SERVICE_NOT_AVAILABLE может произойти, когда часы устройства не синхронизированы с сетью. Опять же, разработчики не могут знать, что это именно та проблема, поэтому мы можем вслепую предложить пользователю проверить синхронизацию системных часов, надеясь, что они одни из немногих, чьи часы не синхронизированы.
  5. SERVICE_NOT_AVAILABLE может произойти, когда пользователь с правами root удалил приложение Hangouts/GTalk со своего устройства (потому что они считали его вредоносным ПО). GCM реализуется и обрабатывается Hangouts/GTalk, поэтому без него невозможно использовать GCM.
  6. SERVICE_NOT_AVAILABLE может произойти, если пользователь использует устройство, на котором не установлены API Google (например, Amazon Kindle). Ничего не поделаешь, эти пользователи никогда не получат Push-уведомления от вашего приложения.

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

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

Альтернатива Google Cloud Messaging

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

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

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

17
Elad Nava

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

Ура

13
Mahendra Liya

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

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

public class MyCustomApp extends Application {

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

}
3
Corbella

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

3
Muhammad Aamir Ali

У меня была похожая проблема. Работал нормально на Google Nexus (Android 4.4.2), но не на Samsung Galaxy S3 (Android 4.1.2) . Я получал SERVICE_NOT_AVAILABLE при регистрации на Samsung. Оказалось, время на Samsung было выключено. Не было установлено автоматическое обновление с сетевым временем. Однажды я установил, что GCM работает как шарм. Спасибо - умешь

3
user3541251

В моем случае решение состояло в том, чтобы добавить новое действие фильтра намерений, РЕГИСТРАЦИЯ, к манифесту, для 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).

3
Brian Marick

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

3
ahmadalibaloch

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

2
Roozbeh Zabihollahi

Для меня проблема 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> Я надеюсь, что это поможет вам :-).

0
Hay Thi

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

Я отказался от попыток найти настройку, которая ему соответствовала, и просто сбросил заводские настройки устройства. Устройства OnePlus, работающие с OxygenOS, иногда получают странные ошибки конфигурации при установке обновлений программного обеспечения, а после сброса к заводским настройкам с последующим восстановлением из Google Backup все работает снова быстрее, чем требуется, чтобы понять основную проблему (и, возможно, у пользователя даже нет правильный доступ, чтобы исправить основную проблему).

0
binki

Я перешел из «Фонового доступа к данным» для служб Google. Сняв флажок «Ограничить фоновые данные» в опции «Использование данных», он работает для меня!

0
Gowtham Venkat

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

0
D.Snap