13
votes

I am trying to use gcm notification. My server code is working fine and I am getting success as acknowledgment.

The problem is notification is getting sent properly :

1) In most of devices notification is received instantaneously. Tested on google nexus,sony phones.

2) Other devices are also receiving notification but after several hours. Yes, hours. Tested on Karbonn, Micromax some phones.

Note:

All the devices are connected to the same wifi so network connectivity not an issue . Using php at server side; There are several unanswered questions regarding this topic . I am hereby listing some of them:

gcm notification is not working on some devices like micromax

One device doesn't receive push notifications (GCM)

Push notifications delay with GCM

Anyone else having similar problem attach your question too.

Failed trials of rectification:

I have also made changes to code after going through several questions in which the developers found their solution like removing this line of code from onHandleIntent()

GcmBroadcastReceiver.completeWakefulIntent(intent);

Or changing delay_while_ideal value to true/false in server code.

Or separately mentioning receiver and registration intent-filter

<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.nothing.gcmclient" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.nothing.gcmclient" />
</intent-filter>

Code: Android.manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.nothing.gcmclient"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="22" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <permission
        android:name="com.nothing.gcmclient.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.nothing.gcmclient.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.nothing.gcmclient.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <uses-permission android:name="ANDROID.PERMISSION.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".RegisterActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden"
            android:label="@string/app_name" >
        </activity>

        <receiver
            android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="com.nothing.gcmclient" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="com.nothing.gcmclient" />
            </intent-filter>
        </receiver>

        <service android:name=".GCMNotificationIntentService"></service>

        <activity
            android:name=".ChatActivity"
            android:label="@string/title_activity_chat" >
        </activity>
        <activity
            android:name=".RegisterScreen"
            android:label="@string/title_activity_register_screen" >
        </activity>
        <activity
            android:name=".RegisterChatButtonActivity"
            android:label="@string/title_activity_register_chat_button" >
        </activity>
        <activity
            android:name=".ChatHistory"
            android:label="@string/title_activity_chat_history" >
        </activity>
        <activity
            android:name=".MessageScreen"
            android:label="@string/title_activity_message_screen" >
        </activity>
    </application>

</manifest>

Code: GCMNotificationIntentService.java

public class GCMNotificationIntentService extends IntentService {

    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;

    public GCMNotificationIntentService() {
        super("GcmIntentService");
    }

    public static final String TAG = "GCMNotificationIntentService";

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

        String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty()) {
            if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
                    .equals(messageType)) {
                sendNotification("Send error: " + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
                    .equals(messageType)) {
                sendNotification("Deleted messages on server: "
                        + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
                    .equals(messageType)) {
                String sender=extras.get(Config.SENDER).toString().toLowerCase();
                String message=extras.get(Config.MESSAGE_KEY).toString();

                if(!RegisterActivity.appVisible==true)
                {
                    sendNotification("New message Received from "+ extras.get(Config.SENDER));
                }
            }
        }
        //GcmBroadcastReceiver.completeWakefulIntent(intent);
    }

    private void sendNotification(String msg) {
        Log.d(TAG, "Preparing to send notification...: " + msg);
        mNotificationManager = (NotificationManager) this
                .getSystemService(Context.NOTIFICATION_SERVICE);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, ChatHistory.class), 0);

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                this).setSmallIcon(R.drawable.gcm_cloud)
                .setContentTitle("New Notification")
                .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setContentText(msg);

        mBuilder.setContentIntent(contentIntent);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
        Log.d(TAG, "Notification sent successfully.");
    }
}

Experts please look into the problem and suggest the appropriate cause and solution. My app would be of no use if it works only for certain phones.If you need any more file in our application kindly inform.

PS- Kindly read the entire question and then post your comments or answers or mark duplicate if necessary.

3
Sounds like either a device problem or a GCM server problem, (probably device). Neither of which you will be able to fixtyczj
Tried it on 7 devices. Failed for three. That percentage is high enough to believe device specific problemuser2653926
You can try two official demo app here and here. If the problem still exist, I think it surely a device specific problem, so maybe you can find some support company by company.bjiang
You must handle gcm registration id properly, actually some times it be very abrupt situation for gcm to identify gcm registration id. Your whole code is good you just handle gcm id properly and update every time.Vishal Jain
@user2653926 Sorry, the correct USSD code is *#*#426#*#* and the here is the link to the corresponding post on google forums: productforums.google.com/forum/#!msg/nexus/fslYqYrULto/…Baris Akar

3 Answers

8
votes
  • GCM works through Google Play Services
  • Devices connect to Google Play Services through TCP on port 5228
  • Devices should use port 443 as fallback if port 5228 is blocked, but apparently they just don't use the fallback sometimes (happened to multiple of my devices)
  • Device sends a heartbeat packet to Google Play Services every 28 minutes on mobile and 15 minutes on wifi
  • You can check the connection state, heartbeat interval, connection address and port, etc. dialing *#*#426#*#* on a device

How to fix common issues when devices don't connect to Google Play Services on wifi or lose connection frequently:

  1. Open port 5228
  2. Configure your routers, so they don't kill inactive tcp connections before waiting at least 15 minutes

See this post on Google Product Forums for more information.

1
votes

I had the same problem.

First, make sure your messages dont exceed the maximum char length. Second, a lot of people told me it could be firewall issues from the phones or network, but other apps (like whatsapp) worked smoothly. After a couple weeks, It stopped the delays and my problems solved alone.

I know this is not a real solution, but try waiting, develop other things and come back to test it again in a couple weeks.

1
votes

Since you receive notifications on some devices as expected I assume your manifest and Java code which you posted basically should be OK. Could you post your GcmBroadcastReceiver-class? It should be something like this:

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

/**
 * Starts GcmIntentService which handles the intent.
 */
@Override
public void onReceive(Context context, Intent intent) {     

    // Explicitly specify that GcmIntentService will handle the intent.
    ComponentName comp = new ComponentName(context.getPackageName(), GCMNotificationIntentService.class.getName());

    // Start the service, keeping the device awake while it is launching.
    startWakefulService(context, (intent.setComponent(comp)));
    setResultCode(Activity.RESULT_OK);
}

This class is responsible for waking up your app (if your app´s process is not running yet) and calling your service, if you do not implement it like this the Android system will not start your GCMNotificationIntentService because the app is not running yet hence no notification can be displayed. This also would explain why the notifications are received on some devices immediately. So I assume you receive the notification on each device, but just not display it instantly.

Furthermore it is definitly not necessary to call GcmBroadcastReceiver.completeWakefulIntent(intent); in the GCMNotificationIntentService if your BroadcastReceiver is correct because this line even cannot have any effect since it is never called (if my assumption is right, that your BroadcastReceiver is the problem).

As far as I see you are using the old version of the GCM-API. I don´t know if you know the newer GCM-API being available since a few weeks. I also had a similar issue with the old version some time ago but since I am using the new API (inlcuding InstanceID-API which replaces the old Registration ID) I was never having any notification-delay-issue anymore.

I can strongly recommmend to implement the new GCM-API. See the docs for further information. And that´s the doc for the InstanceID-API.