Home » Android » java – Google Cloud Messaging – messages either received instantly or with long delay

java – Google Cloud Messaging – messages either received instantly or with long delay

Posted by: admin May 14, 2020 Leave a comment

Questions:

I am using Google cloud messaging in my final year project for college. Everything works okay but I have been having a bit of trouble with GCM. Pretty regularly, messages are either delivered virtually instantly, or with a large delay.

I have read this and I really don’t think it applies in this case:

GCM will usually deliver messages immediately after they are sent.
However, this might not always be possible. For example, the device
could be turned off, offline, or otherwise unavailable. In other
cases, the sender itself might request that messages not be delivered
until the device becomes active by using the delay_while_idle flag.
Finally, GCM might intentionally delay messages to prevent an
application from consuming excessive resources and negatively
impacting battery life.

In my project were talking about at most 5 or 6 messages from the server a minute. If GCM can be used for a chat application surely they couldn’t block messages which are sent / received at this rate? It has become pretty annoying and will pretty badly if my project only works 50% of the time…

Here is my code for the message the server sends:

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

And my Android onMessage method:

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

        }
    });
    */
}

I am hoping somebody has had a similar issue, I just want to confirm that the problem is something I am doing or if it is out of my hands.

tl;dr GCM messages either arrive instantly or about 10 minutes later (the delay is usually consistent).

How to&Answers:

The GCM framework part on the client phone use a TCP connection on the port 5228. This connection its used for push notifications, but as every tcp connection it can go on timeout with some routers/carriers that apply strict policies to kill inactive tcp connections (tcp idle timeout).

Most wifi routers kills inactive connections after 5 minutes for example, like mine.

The GCM framework use a keep-alive mechanism to send an heartbeat network packet every 15 minutes on wifi and every 28 minutes on 3G. This keep-alive is not always reliable for all users.

I opened the issue to google here:
https://productforums.google.com/forum/#!category-topic/nexus/connecting-to-networks-and-devices/fslYqYrULto
They agree there is currently an issue.

EDIT (2014/01/08): currently Google updated the heartbeat intervals to 8 minutes for wifi and mobile connections. Tha’ts a remote change which impact all android devices 2.2+
This is a good improvment to avoid the tcp push connection timeout. Still, if a wifi router kill inactive connections after 5 minutes, you will have a 3 (8-5) minutes delay in push notifications (if you hadn’t other notifications that keep alive the connection)

EDIT (2016/03/06): now google seems to be testing my 2 years ago feedback, to have a dynamic mechanism to determinate the right heartbeat interval depending from the network. Currently seems a staged rollout and only for wifi as for what I know. So based on the wifi SSID the algorithm determine the right heartbeat interval for the specific wifi with a sort of stepwise refinement. This sound very good! This is a remote change which impact every android phone that has Google Play Services.