2013-05-25 163 views
9

我在大學的最後一年項目中使用Google雲消息傳遞。一切正常,但我一直在GCM有點麻煩。相當規律的是,消息要麼實時傳送,要麼延遲很大。Google雲消息傳遞 - 即時收到或延遲收到的消息

我已閱讀這一點,我真的不認爲它適用於這種情況:

GCM通常會立即將消息發送之後。 但是,這可能不總是可能的。例如,設備 可能被關閉,脫機或不可用。在其他 的情況下,發件人本身可能會要求郵件不被傳遞 ,直到設備通過使用delay_while_idle標誌變爲活動狀態。最後,GCM可能會故意延遲消息,以防止應用程序消耗過多的資源,並負面影響電池壽命。

在我的項目中,每分鐘最多隻有5或6條消息。如果GCM確實可用於聊天應用程序,它們不能阻止以此速率發送/接收的消息?它已成爲非常惱人並會相當嚴重,如果我的項目只運作時間的50%......

這裏是我的服務器將郵件發送代碼:

@Override 
public void run() { 

    Message.Builder messageBuilder = new Message.Builder().delayWhileIdle(false); 
    Gson gson = new Gson(); 
    messageBuilder.addData("profile", gson.toJson(profile)); 
    databaseConnection.notifyDevices(messageBuilder.build()); 

} 

public void notifyDevices(Message message) { 

     Sender sender = new Sender(xxx); 

     List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); 
     nameValuePairs.add(new BasicNameValuePair("message", message.toString())); 

     //LOG 
     System.out.println("Notifying devices with the following message \n \"" +message+ "\""); 

     List<String> deviceIDsList = new ArrayList<String>(); 
     String [] deviceIDArray; 

     //Get devices to notify 
     List<JSONDeviceProfile> deviceList = getDevicesToNotify(); 

     for(JSONDeviceProfile device : deviceList) { 
      deviceIDsList.add(device.getDeviceId()); 

      try { 
       sender.send(message, device.getDeviceId(), 5); 
      } catch (IOException e) { 
       System.out.println("Error sending GCM message!"); 
       e.printStackTrace(); 
      } 
     } 
} 

而且我的Android onMessage方法:

@Override 
protected void onMessage(Context arg0, Intent intent) { 

    String message = intent.getStringExtra("profile"); 

    Log.d(TAG + "Received Message: ", "Received Message: " + message.toString()); 

    //CALL NEW INTENT WITH PROFILE DETAILS 
    Intent displayProfileIntent = new Intent(arg0, DisplayProfile.class); 
    displayProfileIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    displayProfileIntent.putExtra("message", message); 
    startActivity(displayProfileIntent); 

    /* 
    //generateNotification(arg0, username); 

    handler.post(new Runnable() { 
     @Override 
     public void run() { 
      //Toast.makeText(getApplicationContext(), username, Toast.LENGTH_SHORT).show(); 

     } 
    }); 
    */ 
} 

我希望有人有過類似的問題,我只是想確認問題是什麼我做的,或者如果它是從我手中。 GCM消息要麼​​立即到達,要麼大約10分鐘後(延遲通常一致)到達。

回答

29

客戶端手機上的GCM框架部分使用的端口5228.用於推送通知這個連接其上TCP連接,而且是每一個TCP連接,它可以繼續暫停時以適用嚴格的政策,一些路由器/運營商終止非活動的TCP連接(tcp空閒超時)。

大多數wifi路由器在5分鐘後殺死非活動連接,例如像我的一樣。

GCM框架使用keep-alive機制在wifi上每15分鐘發送一次心跳網絡數據包,在3G上每28分鐘發送一次心跳網絡數據包。對於所有用戶而言,這種保持活力並不總是可靠的。

我把問題打到谷歌這裏: https://productforums.google.com/forum/#!category-topic/nexus/connecting-to-networks-and-devices/fslYqYrULto 他們同意,目前有一個問題。

編輯(2014/01/08):目前Google更新了無線和移動連接的心跳間隔爲8分鐘。這是一個影響所有Android設備的遠程更改2.2+ 這是避免tcp push連接超時的一個很好的改進。但是,如果wifi路由器在5分鐘後終止非活動連接,則推送通知將會有3(8-5)分鐘的延遲(如果您沒有其他通知可保持連接活躍)

編輯(2016/03/06):現在谷歌似乎在測試我2年前的反饋,有一個動態機制來確定正確的心跳間隔取決於網絡。目前似乎是一個階段性的推出,只爲了我所知道的無線網絡。因此,基於wifi SSID,該算法通過逐步細化來確定特定wifi的正確心跳間隔。這聲音非常好!這是一個遠程更改,會影響到每個擁有Google Play服務的Android手機。

+1

嗨andQlimax,請你分享一下你的「推送通知修復程序」的代碼?非常感謝! – injecteer

+0

嗨injecteer,認爲我的應用程序只適用於根植電話 – andQlimax

+0

嗨,我也讀過它。因此,我決定使用長輪詢來代替GCM的應用程序的關鍵部分。無論如何謝謝澄清 – injecteer