Google Cloud Messaging - 即时收到或延迟收到的邮件

时间:2013-05-25 11:24:30

标签: java android google-cloud-messaging

我在大学的最后一年项目中使用Google云消息传递。一切正常,但我在使用GCM时遇到了一些麻烦。很多时候,消息几乎是立即发送,或者延迟很长。

我已经读过这篇文章了,我认为它不适用于这种情况:

  

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();

        }
    });
    */
}

我希望有人遇到过类似的问题,我只是想确认问题是我正在做的事情,或者是不在我手中。

tl; dr GCM消息要么​​立即到达,要么在10分钟后到达(延迟通常是一致的)。

1 个答案:

答案 0 :(得分:30)

客户端电话上的GCM框架部分在端口5228上使用 TCP连接。此连接用于推送通知,但是作为每个tcp连接,它可以与某些路由器/运营商一起超时应用严格的策略来终止非活动的tcp连接( tcp idle timeout )。

大多数wifi路由器会在5分钟后杀死非活动连接,例如我的。

GCM框架使用 keep-alive 机制在wifi上每15分钟发送一次心跳网络数据包,在3G上每28分钟发送一次。对于所有用户而言,这种保持活力并不总是可靠的。

我在这里向谷歌打开了这个问题: https://productforums.google.com/forum/#!category-topic/nexus/connecting-to-networks-and-devices/fslYqYrULto 他们同意目前存在问题。

EDIT(2014/01/08):目前,Google将心跳间隔更新为8分钟,用于wifi和移动连接。这是一个影响所有Android设备2.2+的远程变化 这是避免tcp推送连接超时的一个很好的改进。尽管如此,如果一个wifi路由器在5分钟后终止非活动连接,你将会有3(8-5)分钟的推送通知延迟(如果你还没有其他通知可以保持连接)

编辑(2016/03/06):现在谷歌似乎正在测试我2年前的反馈,有一个动态机制来根据网络确定正确的心跳间隔。目前似乎是一个阶段性的推出,只有wifi我知道。因此,基于wifi SSID,算法通过一种逐步细化来确定特定wifi的右心跳间隔。这听起来很棒!这是一个远程更改,它会影响每个拥有Google Play服务的Android手机。