Intereting Posts
Сделать навигационную панель максимально активной анимации активности Android Yelp, как панель поиска в ActionBar В чем разница между `DialogInterface.dismiss ()` и `DialogInterface.cancel ()`? Пользовательский агент Android HTTP Как открыть программу электронной почты через Intents (но только программу электронной почты) AccountManagerFuture.getResult () приводит к экрану «Не удалось войти» Android Support Library 23.2.0, вызывающая стрелку панели инструментов черным Во время экспорта подписанного приложения сбой eclipse Различать тайм-аут экрана и нажатия кнопки питания? Чистое Blank Android-приложение не удается построить – «не удалось найти версию средств для сборки 23.0.0 rc1» Хорошо ли использовать только GCM для разработки чат-приложений для XMPP-андроида? Не удалось найти команду com.android.camera.CropImage в android Как удалить фрейм устройства на эмуляторах Android Studio Dialog.setTitle не показывает заголовок Обратный вызов клиента google api никогда не вызывается

Google Cloud Messaging – сообщения, которые иногда не принимаются, пока не изменилось состояние сети

Работая над небольшим проектом, который интегрируется с GCM, я наткнулся на немного странную проблему.

Несколько раз, когда я начинаю наблюдать за журналом, чтобы узнать, получены ли сообщения, сообщения не появляются до тех пор, пока я не изменил состояние сети (IE первоначально на WiFi, если я отключу WiFi и перейду к Mobile Data, сообщения придут отлично). После того, как я изменил состояние сети, сообщения начнут поступать совершенно нормально, и то же самое произойдет, как только я изменю состояние сети до того, что было раньше (в данном случае, WiFi), сообщения продолжают поступать.

Сам проект включает в себя возможность запускать при загрузке (запускает GCMBaseIntentService при загрузке), что также отлично работает, и я уверен, что приложение / служба запущено, так как я вручную запустил приложение, когда эта проблема возникает (что Также проверяет, работает ли служба, и если она не запускает ее и проверяет, зарегистрирована ли она).

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

Оцените любую помощь – я могу предоставить источник, если это необходимо, хотя он вряд ли отклоняется от демонстрационного приложения, представленного в android-sdk.

Solutions Collecting From Web of "Google Cloud Messaging – сообщения, которые иногда не принимаются, пока не изменилось состояние сети"

Я тоже это заметил. Хотя я не вникнул в настоящий код, вот мое понимание того, почему это происходит.

GCM (и большинство служб обмена сообщениями) работает, поддерживая долгоживущий сокет, открытый для сервера push-уведомлений Google. Сокет остается открытым, отправляя сообщения «heartbeat» между телефоном и сервером.

Иногда состояние сети может измениться, и этот сокет будет поврежден (потому что IP-адрес устройства изменяется, например, от 3g до Wi-Fi). Если сообщение появляется до того, как сокет будет восстановлен, то устройство не получит сразу сообщение.

Повторное соединение происходит только тогда, когда телефон уведомляет о сбое сокета, что происходит только тогда, когда он пытается отправить сообщение с биением.

Опять же, просто мое основное понимание того, как это работает и почему это происходит, и я мог ошибаться.

Существует множество причин задержки сообщений GCM. Если сообщение начинает появляться после изменения состояния сети или включения / выключения режима полета – наиболее вероятной причиной является сеть, которая закрывает соединение, не отправляя FIN / RST.

GCM поддерживает долговременное соединение и повторно подключается, если знает, что соединение было нарушено. Предполагается, что маршрутизатор / AP / NAT отправит FIN или RST для завершения TCP-соединения – поэтому GCM и серверы будут знать, что соединение мертво.

Однако ряд маршрутизаторов и мобильных операторов этого не делают, и тогда GCM необходимо полагаться на сердцебиение, ~ 15 минут на Wi-Fi, больше на мобильных устройствах. Существует компромисс между временем автономной работы / использованием сети и частотой пульса.

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

private boolean isNetworkAvailable() { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null; } 

Поэтому, если @theelfismike мышление верно, могу ли я использовать что-то вроде:

  ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); if (null != activeNetwork) { if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) // here the network changed to Wifi so I can send a heartbeat to GCM to keep connection if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) //here the network changed to mobileData so I can send a heartbeat to GCM to keep connection } 

Мое решение хорошее?

В классе GCMIntentSevice, когда вы получаете сообщение от сервера, метод onMessage вызывается так, что в то время вы можете сделать что-то вроде …

 PowerManager pm = (PowerManager) getApplicationContext() .getSystemService(Context.POWER_SERVICE); WakeLock wakeLock = pm.newWakeLock( (PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP),"TAG"); wakeLock.acquire(); 

И вы должны добавить

<uses-permission android:name="android.permission.WAKE_LOCK" /> разрешение в вашем файле манифеста ..

Это должно сделать трюк …