1

I am implementing GCM in my application. I have followed all the steps given in GCM tutorial from developer.android.com

My application's build target is pointing to Goolge API 8 (Android 2.2 version).

I am able to get the register ID from GCM successfully, and I am passing this ID to my application server. So the registration step is performed successfully.

Now when my application server sends a PUSH message to my device, the server gets the message as SUCCESS=1 FAILURE=0, etc., i.e. Server is sending message successfully, but my device never receives the message.

After searching alot about this, I came to know that GCM pushes messages on port number 5228, 5229 or 5230.

Initially, my device and laptop was restricted for some websites, but then I was granted all the permissions to access all websites, so I guess these port numbers are open for my device.

So my question is: Very few times, I am receiving PUSH message from GCM. Why Google is so uncertain in delivering messages? What could be the reason?

Please see my following code and guide me accordingly:

I have declared following in my manifest:

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

    <permission
        android:name="package.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <!-- App receives GCM messages. -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <!-- GCM connects to Google Services. -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- GCM requires a Google account. -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    <!-- Keeps the processor from sleeping when a message is received. -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="package.permission.C2D_MESSAGE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <receiver
            android:name="com.google.android.gcm.GCMBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

                <category android:name="packageName" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".ReceiveBroadcast"
            android:exported="false" >
            <intent-filter>
                <action android:name="GCM_RECEIVED_ACTION" />
            </intent-filter>
        </receiver>

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


/**
 * @author Shrikant.
 * 
 */
public class GCMIntentService extends GCMBaseIntentService {

    /**
     * The Sender ID used for GCM.
     */
    public static final String SENDER_ID = "myProjectID";

    /**
     * This field is used to call Web-Service for GCM.
     */
    SendUserCredentialsGCM sendUserCredentialsGCM = null;

    public GCMIntentService() {
        super(SENDER_ID);
        sendUserCredentialsGCM = new SendUserCredentialsGCM();
    }

    @Override
    protected void onRegistered(Context arg0, String registrationId) {
        Log.i(TAG, "Device registered: regId = " + registrationId);
        sendUserCredentialsGCM.sendRegistrationID(registrationId);
    }

    @Override
    protected void onUnregistered(Context context, String arg1) {
        Log.i(TAG, "unregistered = " + arg1);
        sendUserCredentialsGCM
                .unregisterFromGCM(LoginActivity.API_OR_BROWSER_KEY);
    }

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.e("GCM MESSAGE", "Message Recieved!!!");
        String message = intent.getStringExtra("message");
        if (message == null) {
            Log.e("NULL MESSAGE", "Message Not Recieved!!!");
        } else {
            Log.i(TAG, "new message= " + message);
            sendGCMIntent(context, message);
        }
    }

    private void sendGCMIntent(Context context, String message) {
        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction("GCM_RECEIVED_ACTION");
        broadcastIntent.putExtra("gcm", message);
        context.sendBroadcast(broadcastIntent);
    }

    @Override
    protected void onError(Context context, String errorId) {
        Log.e(TAG, "Received error: " + errorId);
        Toast.makeText(context, "PUSH Notification failed.", Toast.LENGTH_LONG)
                .show();
    }

    @Override
    protected boolean onRecoverableError(Context context, String errorId) {
        return super.onRecoverableError(context, errorId);
    }
}

Thanks.

Shrikant Ballal
  • 7,067
  • 7
  • 41
  • 61
  • Have you **confirmed** that those ports are open on your device? You might want to use an online port testing tool to verify that those ports are all open. I don't think you can assume those ports are open based on what you've said. If you want to test a known working GCM project on your device, there is a sample app available on Github: http://github.com/indigorose/airbop-client – Lorne Laliberte Nov 30 '12 at 23:40
  • (AirBop is a third-party GCM registration service which can be used for free up to 1000 devices.) – Lorne Laliberte Nov 30 '12 at 23:47
  • If those ports were closed on my side, i would have never received PUSH messages, but have I received PUSH messages sometimes(very few times). – Shrikant Ballal Dec 01 '12 at 09:59
  • Can you tell me, why GCM is not able to send me PUSH messages? I can try AirBop, but as Google is free, my first choice would be to use Google service. I am absolutely clueless why I am not receiving PUSH messages. – Shrikant Ballal Dec 01 '12 at 10:04
  • (Just to be clear, AirBop uses GCM -- GCM itself is free, but you still need a server side component to handle the device registration IDs.) What GCM settings are you using when you send the push messages? There are several instances where you might not receive the message, for instance if you set dry_run to true, or if you use a collapse key. For example, if you're setting a different collapse key with each message, you will definitely lose some messages, because GCM only supports a maximum of 4 collapse keys at any given time. – Lorne Laliberte Dec 03 '12 at 18:12
  • Thanks Lorne, I will check if different collapse key is used on server side, and will update you. Between, can you tell me what's use of "Dry Run" ? I searched it, but could not understand the usage. Thanks. – Shrikant Ballal Dec 04 '12 at 05:11
  • If you set dry_run to true, the GCM server will process the message without delivering it to any devices. It serves two purposes: (1) it tests your message parameters, e.g. your JSON is correct and no values are out of range, and (2) it can refresh your server's view of the registration ids, e.g. if GCM learned that some clients were uninstalled the last time it attempted to deliver a push notification, it will report those registration ids among the list of failures in its response to your dry run. So in other words it's a chance for your server to drop lost ids without sending a msg. – Lorne Laliberte Dec 04 '12 at 16:55
  • One other situation where your app won't receive the message is if you force stopped the app (i.e. tapped the Force Stop button on the app's info page in device settings). Once an app is forcibly stopped by the user, that app's broadcast receivers will no longer be called. The app will only begin receiving broadcasts again if the app is launched by the user, effectively clearing the "stopped" flag for that app. – Lorne Laliberte Dec 04 '12 at 19:21
  • Okay thanks a lot. Now I checked it on server side if we are using either dry run or collapse key, we are not using it. And also I am not forcibly closing my application. I have noticed that, when I send PUSH notifications from server side (freshly, for the first time) I receive the PUSH message, but after that, when I send it again, i.e. consecutive times, I don't receive it after that. I don't know what happens to those messages. – Shrikant Ballal Dec 05 '12 at 04:56
  • Few more things to check. What JSON are you sending to GCM? Your onMessage is retrieving 'message' as a string, what are you passing as 'message' in the bundle, i.e. as data.message in the JSON? Does your onMessage() method get called? What do you see in logcat? Your custom permission uses android:name="package.permission.C2D_MESSAGE" but your receiver's category is android:name="packageName", they should be the same in your source code...are they? – Lorne Laliberte Dec 05 '12 at 08:28
  • Can you post your Server Side Code please, the java code seems correct, perhaps the problem is that your server isn't sending the message to the cloud server each time? Have a look at this : http://stackoverflow.com/questions/13079840/how-to-call-the-c2dm-php-function-from-the-android-app – Ushal Naidoo Dec 06 '12 at 04:13

3 Answers3

2

Check whether the debug certificate is expired or not, If it is then create new certificate and generate new key.

user1527969
  • 66
  • 1
  • 6
0

Try to change your class names as full names with package names. Like:

<service android:name="com.xx.xx.xx" />

And dont forget to put your package name here:

<category android:name="packageName" />
Mustafa Genç
  • 2,569
  • 19
  • 34
  • You should be sure about your package names are correctly written in manifest file. That must be the problem. – Mustafa Genç Oct 27 '12 at 10:22
  • I have already put that in the receiver, should I put it inside service tag? There is no category tag in Service tag. I didn't understand what you are saying. Do I have to start the service, because I haven't started my service, but still I get the registration, so can there be any problem with my service? – Shrikant Ballal Oct 27 '12 at 10:23
  • the package name is correct. I have not mentioned it on this post. – Shrikant Ballal Oct 27 '12 at 10:24
  • I mean you have written in your receiver tag. Are you sure that you have written its name correctly? – Mustafa Genç Oct 27 '12 at 10:26
  • Also for service tag use full package name as I wrote in my answer – Mustafa Genç Oct 27 '12 at 10:28
  • @Shrikant: Did you found solution for this issue. Struggling on the same problem.. Any help please. Thank You –  Nov 21 '12 at 10:52
  • I am not sure if that will be the answer or not to your problem but since message is string if Statment sholud be something like If(message.equlaes(null)) or message.equlaes("") rather than message == null – Husam A. Al-ahmadi Dec 04 '12 at 10:41
0

Make sure your app name and the name you registered on the google console for getting api key are same name.Same name in the sense that exactly the same

DeepakAndroid
  • 137
  • 1
  • 8