2012-12-12 55 views
40

在與GCM集成的小項目上工作時,我遇到了一些奇怪的問題。Google Cloud Messaging - 在網絡狀態發生變化時有時收不到消息

有些時候,當我開始觀看日誌以查看是否收到消息時,直到我改變了網絡狀態(IE本來在WiFi上,如果我關閉WiFi並移動到移動數據,消息到達正常)。在我改變了網絡狀態之後,消息開始得到完全正常,並且一旦我將網絡狀態改回到之前的狀態(在這種情況下,WiFi),這些消息繼續被接收。

該項目本身包括啓動時啓動的能力(啓動時啓動GCMBaseIntentService),這再次正常工作,我敢肯定應用程序/服務正在運行,因爲我手動啓動應用程序時問題發生(它也會檢查服務是否正在運行,如果沒有運行它並檢查它是否已註冊)。

有其他人遇到這個問題,或者有任何指針,我怎麼能解決這個問題?在沒有收到消息的時間和消息之間的日誌之間(改變網絡狀態之後),我沒有看到任何幫助。我瀏覽過GCM文檔,看不到由於超時(在設備本身上)而未收到消息的任何提示,或任何可能影響此設置的配置選項。

欣賞任何幫助 - 我可以提供源如果需要的話,雖然它很難從Android的SDK提供的演示程序偏離。

在GCMIntentSevice類
+2

是的,我看到和其他人一樣。無線上網時收到即時消息,通過3g可變延遲。打開飛行模式,然後關閉會顯示消息。我在Google開發人員小組中添加了一條評論(目前我無法找到!)。我的設備是一個三星Galaxy S2 – NickT

+0

謝謝 - 我明白,與WiFi相比,3G會稍微延遲,但我的觀點是,有時消息並沒有達到。但是,當我切換網絡(即從WiFi到3G或反之亦然)消息開始再次出現。我會很感激鏈接到您發佈的評論/主題以供參考:)感謝p.s.我也在Galaxy S2上。 – Seidr

+1

嗨鏈接是https://groups.google.com/forum/?fromgroups=#!topic/android-gcm/bsYumo68fsc。我的手機是O2。我總是最終收到郵件,但最多可能需要30分鐘。我在倫敦有一個很強的(通常是H +)信號。 – NickT

回答

36

我也注意到了這一點。雖然我還沒有深入到實際的代碼中,但這是我對這種情況發生的理解。

GCM(最推送消息服務)的工作原理是保持一個長期套接字打開谷歌的推送通知服務器。通過在手機和服務器之間發送「心跳」消息,套接字保持打開狀態。

有時,網絡狀態可以改變,這插座將被打破(因爲該設備的IP地址改變,從3G到無線網絡,例如)。如果在套接字重新建立之前消息進入,那麼設備將不會立即收到消息。

的重新連接,只有當手機注意到插座壞了,當它試圖發送一個心跳消息僅發生情況。

再一次,只是我對它是如何工作以及爲什麼會發生的基本理解,而且我可能是錯的。

+0

已接受您的答案,因爲目前似乎沒有解決方案,但您的回答最能說明問題的根源。 – Seidr

+0

你明白了,GCM不能很好地處理TCP超時,請參閱:http:// stackoverflow。com/questions/16749038/google-cloud-messaging-messages-either-received-instant-or-with-long-delay/18428357#18428357 – andQlimax

-4

,當你從服務器接收消息,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" /> 許可,您清單文件..

這應該做的伎倆...

+1

謝謝你的回答,但是活着的狀態在這裏不是問題。我認爲這與長期存在的連接丟失有關,而不是及時重新創建。 – Seidr

1

按在上面的回答您的意見,並根據我的GCM推送通知的體驗沒有任何的理由是如果網絡(互聯網連接),可您不應該收到推送通知我一直在運行前檢查互聯網連接的可用性像這樣的推送通知應用程序嘗試檢查,如果這是真的,你應該會收到推送通知

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

你嘗試過嗎? –

19

GCM消息延遲有很多原因。如果在更改網絡狀態或打開/關閉飛行模式之後消息開始到達 - 最可能的原因是網絡在不發送FIN/RST的情況下關閉連接。

GCM保持長時間連接 - 如果知道連接中斷,則重新連接。 路由器/ AP/NAT應該發送FIN或RST來終止TCP連接 - 所以GCM和服務器將知道連接已經死亡。

但是,許多路由器和移動運營商不這樣做,然後GCM需要依賴心跳,在Wifi上約15分鐘,更多在手機上。在電池壽命/網絡使用和心跳頻率之間進行權衡。

+0

對此的實際原因有很好的技術擴展。 – Seidr

0

所以,如果@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 
    } 

是我的解決方案好?

+0

不必要的,GCM自動執行此操作 –