GCM does not work on Gingerbread, but does work on Ice Cream Sandwich

I am writing a game that uses GCM messages. When one player enters a turn, moves to the server, the server sends a GCM message to its opponent, letting the client know that additional turn data is available. It should be simple. I followed the GCM client code sample as closely as possible.

I have two devices to test: Motorola Xoom with Ice Cream Sandwich version 4.0.4 Motorola X2 with Gingerbread version 2.3.5

Both devices have a Goggle account setup (actually the same account). I can download apps from the Play Store on both. I get notified of this when I receive a new Google Talk message or Gmail message. They are both in front of me using the same Wi-Fi network, so I can confirm that there are no firewall issues. I have the same game app installed on both. I was able to get the GCM registration ID on both devices. Apart from the Android OS version, both devices are almost identical. However, Xoom will receive GCM messages and X2 will not, or at least the messages are not streaming to my app on X2.

This is my manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="myGame.app.main" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="myGame.app.main.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="myGame.app.main.permission.C2D_MESSAGE" />

<application android:icon="@drawable/icon" android:name="myGameApp" android:label="@string/app_name" android:description="@string/description" android:theme="@style/GlobalTheme" android:killAfterRestore="false" android:allowTaskReparenting="false" android:persistent="false">

    ... Other Activities ...

    <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="myGame.app.main" />
        </intent-filter>
    </receiver>
    <service android:name=".GCMIntentService" android:enabled="true" />
    </application>
</manifest>

      

This is the code for my GCMIntentService:

package myGame.app.main;

import com.google.android.gcm.GCMBaseIntentService;
import com.google.android.gcm.GCMRegistrar;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import java.util.logging.Logger;

public class GCMIntentService extends GCMBaseIntentService
{
    private static PowerManager.WakeLock sWakeLock;
    private static final Object LOCK = GCMIntentService.class;
    private static final String GCM_SENDER_ID = "... My Sender ID...";
    private static final String GCM_INTENT_FILTER = "myGame.app.main.GCM_MESSAGE";
    private static final String MESSAGE_TYPE = "Type";
    private static final String MESSAGE_CONTENT = "Body";
    private static Logger log = Logger.getLogger(GCMIntentService.class.getName());

    public GCMIntentService()
    {
        super(GCM_SENDER_ID);
    }

    static void runIntentInService(Context context,Intent intent)
    {
        synchronized(LOCK)
        {
            if (sWakeLock == null)
            {
                PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
                sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"sc_wakelock");
            }
        }
        sWakeLock.acquire();
        intent.setClassName(context,GCMIntentService.class.getName());
        context.startService(intent);
    }

    @Override protected void onRegistered(Context context,String registrationId)
    {
        log.warning("From GCMIntentService: Device successfully registered as "+registrationId);
        ... Other Code ...
    }

    @Override protected void onUnregistered(Context context,String registrationId)
    {
        log.warning("From GCMIntentService: Device successfully unregistered");
        ... Other Code ...
    }

    @Override protected void onMessage(Context context,Intent messageIntent)
    {
        log.warning("From GCMIntentService: Game update notice received");
        ... Other Code ...
    }

    @Override protected void onDeletedMessages(Context context,int total)
    {
        log.warning("From GCMIntentService: Server deleted "+Integer.toString(total)+" pending messages");
    }

    @Override public void onError(Context context,String errorId)
    {
        log.warning("From GCMIntentService: Error "+errorId);
        ... Other Code ...
    }

    @Override protected boolean onRecoverableError(Context context,String errorId)
    {
        log.warning("From GCMIntentService: Recoverable error "+errorId);
        return(super.onRecoverableError(context,errorId));
    }
}

      

I even went as far as creating my own GCMBroadcastReceiver class with my own getGCMIntentServiceClassName () function and put the log message there. In every variation I've tried, I see the correct LogCat messages when the app is running in Xoom, but I don't see any evidence of any GCM messages at all on X2. It looks like GCMBroadcastReceiver and / or GCMIntentService aren't working at all, but I don't see any error messages of any kind.

Can anyone help me with this?

0


source to share


1 answer


I have compiled sample code for GCM messages. The only changes I made was to use the same API key and Sender ID that I use in my game app. This app works on both devices, so I can confirm that there are no network problems and I can confirm that X2 can indeed accept GCM messages.

The bad news was that X2 was still not receiving GCM messages for my game. After some research, I found that when the server tries to send a GCM message to X2 (for my game app only) the server gets an ERROR_NOT_Rregistered result. There is no such error sending in Xoom. I have verified that the server is successfully receiving registration IDs. I know this is difficult to tell, but registration IDs will not be mangled during the transfer.



I tried several different posted guidelines on how to unregister a device from the GCM server, but none of them worked. I got the same registration ID again. So I completely uninstalled my game and then reinstalled it on X2. This caused him to get a new registration ID which solved the problem. My game now works on both devices. I have to assume that somehow the registration ID got messed up somehow between the game and the GCM server when I debugged.

I can only hope this does not become a common problem as there seems to be no fix other than uninstalling the application.

0


source







All Articles