Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird push message received on app start

I'm getting a weird push message captured by my push service:

Bundle[{CMD=RST_FULL, from=google.com/iid, android.support.content.wakelockid=1}]

Just started to happen yesterday and I can't really spot which code change is to blame for this. Has anyone seen this message before and maybe knows where is it coming from and why?

like image 515
vkislicins Avatar asked May 27 '15 10:05

vkislicins


4 Answers

Your app is getting this message because it has had data restored from a backup. As the backup may have included registration tokens, this broadcast is sent telling your app to get new tokens as the backed up ones will not work.

This is intended for the new GCM APIs, and it will cause your InstanceIdListenerService implementation's onTokenRefresh() method to be called, where your app should obtain all its tokens again.

Unfortunately, if you are writing your own BroadcastReceiver, these messages will be unexpected and may cause your app to crash. The right thing to do is to filter on the "from" field, and if you see one of these messages, to register again with GCM as your tokens may be invalid.

If you are getting these messages outside the situation of a fresh install where your app's data is being restored, please post to the android-gcm mailing list.

like image 155
morepork Avatar answered Nov 12 '22 05:11

morepork


See the updated GCM API Docs as @morepork suggests.

For existing apps that extend a WakefulBroadcastReceiver, Google recommends migrating to GCMReceiver and GcmListenerService. To migrate:

In the app manifest, replace your GcmBroadcastReceiver with "com.google.android.gms.gcm.GcmReceiver", and replace the current service declaration that extends IntentService to the new GcmListenerService

Remove the BroadcastReceiver implementation from your client code

Refactor the current IntentService service implementation to use GcmListenerService

For details, see the example manifest and code samples in this page.

From their sample code, it's pretty easy to follow.

AndroidManifest.xml

<receiver
    android:exported="true"
    android:name="com.google.android.gms.gcm.GcmReceiver"
    android:permission="com.google.android.c2dm.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
        <category android:name="com.example.client"/>
    </intent-filter>
</receiver>

<service
    android:name=".MyGcmListenerService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
    </intent-filter>
</service>

<service
    android:name=".MyInstanceIdListenerService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.gms.iid.InstanceID"/>
    </intent-filter>
</service>

<service
    android:name=".MyGcmRegistrationService"
    android:exported="false">
</service>

MyGcmListenerService.java

public class MyGcmListenerService extends GcmListenerService {
    @Override
    public void onMessageReceived(String from, Bundle data) {
        final String message = data.getString("message");
        makeNotification(message);
    }
}

MyGcmRegistrationService.java

public class MyGcmRegistrationService extends IntentService {
    private static final String TAG = "MyRegistrationService";
    private static final String GCM_SENDER_ID = "XXXXXXXXXXXX";
    private static final String[] TOPICS = {"global"};

    public MyGcmRegistrationService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        try {
            synchronized (TAG) {
                InstanceID instanceID = InstanceID.getInstance(this);
                String token = instanceID.getToken(GCM_SENDER_ID,
                        GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
                sendTokenToServer(token);
                subscribeTopics(token);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void subscribeTopics(String token) throws IOException {
        for (String topic : TOPICS) {
            GcmPubSub pubSub = GcmPubSub.getInstance(this);
            pubSub.subscribe(token, "/topics/" + topic, null);
        }
    }
}

MyInstanceIdListenerService.java

public class MyInstanceIdListenerService extends InstanceIDListenerService {
    public void onTokenRefresh() {
        Intent intent = new Intent(this, MyGcmRegistrationService.class);
        startService(intent);
    }
}

Then you can replace your old registration code with just

Intent intent = new Intent(this, MyGcmRegistrationService.class);
startService(intent);
like image 37
mpkuth Avatar answered Nov 12 '22 06:11

mpkuth


I realized the same issue today. First, this message must come from google itself (from=google.com/iid), otherwise the from attribute would be the id of your project in google developer console (i.e. 475832179747). But to be sure, I shutdown our application server, and I still received the message.

I always receive it when I newly register at the Google Cloud Messaging server. It's not a big problem because you can filter the message by the intent-action, but I would really like to know the purpose of it.

like image 7
rickul Avatar answered Nov 12 '22 05:11

rickul


For existing apps that extend a WakefulBroadcastReceiver, Google recommends migrating to GCMReceiver and GcmListenerService. To migrate:

  • In the app manifest, replace your GcmBroadcastReceiver with "com.google.android.gms.gcm.GcmReceiver", and replace the current service declaration that extends IntentService to the new GcmListenerService
  • Remove the BroadcastReceiver implementation from your client code
  • Refactor the current IntentService service implementation to use GcmListenerService For details, see the example manifest.

it seems google split the GCMIntentService which extended IntentService to handle gcms to two services, one extends GcmListenerService that will handle received messages and other that filter iid.InstanceID separately to filter out that notification received for first installation, this is from new gcm android guides

<service
    android:name="com.example.MyGcmListenerService"
    android:exported="false" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>
<service
    android:name="com.example.MyInstanceIDListenerService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.gms.iid.InstanceID"/>
    </intent-filter>
</service>

https://developers.google.com/cloud-messaging/android/client

like image 2
nosaiba darwish Avatar answered Nov 12 '22 05:11

nosaiba darwish