【问题标题】:Google Cloud Messaging - messages either received instantly or with long delayGoogle Cloud Messaging - 即时收到或延迟很长时间收到的消息
【发布时间】:2013-05-25 11:24:29
【问题描述】:

我在大学最后一年的项目中使用 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 分钟后到达(延迟通常是一致的)。

【问题讨论】:

    标签: java android google-cloud-messaging


    【解决方案1】:

    客户端电话上的 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 他们同意目前存在问题。

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

    编辑 (2016/03/06):现在 google 似乎正在测试我 2 年前的反馈,以建立一个动态机制来根据网络确定正确的心跳间隔。目前似乎是分阶段推出,据我所知仅适用于 wifi。因此,基于 wifi SSID,该算法通过一种逐步细化的方式确定特定 wifi 的正确心跳间隔。这声音非常好!这是一项远程更改,会影响每部具有 Google Play 服务的安卓手机。

    【讨论】:

    • 嗨,Qlimax,你能分享一些你的“推送通知修复程序”的代码吗?非常感谢!
    • 您好注入者,请考虑我的应用程序仅适用于有根手机
    • 嗨,我也读过。因此,我决定对我的应用程序的关键部分使用长轮询而不是 GCM。无论如何感谢您的澄清
    • 关于 Google 更改心跳间隔的任何消息来源?这是我读过的唯一一个被改变的地方。
    • @KristianErikTigersjäl 上次我检查它时,一年前,计算了心跳间隔并且不再固定。例如。您连接到 wifi sid "123",它每 x 分钟尝试一次,如果 X 分钟后超时,下一次将尝试 X-1 分钟,直到找到适合该连接的那个
    猜你喜欢
    • 2014-02-11
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-09
    • 2020-08-11
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多