0

We have about 900 Android device tokens in our database for GCM push notifications.

I use this PHP function to send the push instruction to the GCM server:

function send_android_push($android_gcm_reg_ids, $title, $message, $activityToLaunch) {

    global $ANDROID_GCM_API_KEY, $TESTING, $TEST_ANDROID_DEVICE_REG_ID;

    if ($TESTING) {
        $android_gcm_reg_ids = [
            $TEST_ANDROID_DEVICE_REG_ID
        ];
    }

    $url = "https://android.googleapis.com/gcm/send";

    $data = array(
        "title" => $title,
        "message" => $message,
        "activityToLaunch" => $activityToLaunch,
    );

    $post = array(
        'registration_ids' => $android_gcm_reg_ids,
        'data' => $data
    );

    $headers = array(
        'Authorization: key=' . $ANDROID_GCM_API_KEY,
        'Content-Type: application/json'
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
    $result = curl_exec($ch);

    if (curl_errno($ch)) {
        $result .= "<br />GCM error: " . curl_error($ch);
    }

    curl_close($ch);

    return $result;
}

Here is a snippet of the JSON content returned by that function/GCM:

{
   "multicast_id":5609284883833846123,
   "success":493,
   "failure":401,
   "canonical_ids":20,
   "results":[
      {
         "registration_id":"BPA91bHP29l2j6NPOldcpAvJCJBGk8oQFErfwuh93cxF8ajJJqBlVGqFcxMDEAc2LL2GKwmP86of49UgBTMycB5IdYergWRBETDNUrnzXX_55FgstCZiauPeD7MokIIPOFoOyW9vCRiBqZhlzLCuSnJ1ENFYtIh_PQ",
         "message_id":"0:1462275569015808%814cce86f9fd7ece"
      },
      {
         "registration_id":"BPA91bHP29l2j6NPOldcpAvJCJBGk8oQFErfwuh93cxF8ajJJqBlVGqFcxMDEAc2LL2GKwmP86of49UgBTMycB5IdYergWRBETDNUrnzXX_55FgstCZiauPeD7MokIIPOFoOyW9vCRiBqZhlzLCuSnJ1ENFYtIh_PQ",
         "message_id":"0:1462275569015815%814cce86f9fd7ece"
      },
      {
         "message_id":"0:1462275569014983%814cce86f9fd7ece"
      },
      {
         "error":"NotRegistered"
      },
      {
         "message_id":"0:1462275569017976%814cce86f9fd7ece"
      },
etc., etc.

It seems to be saying I have device tokens in my database that are NotRegistered but, as you can see, it doesn't tell me which device token isn't registered so I am wondering how I can mark it as obsolete in my database?

I thought that maybe the elements of the JSON array returned by the GCM server might correspond to the $android_gcm_reg_ids array I pass into my send_android_push(...) function but that can't be the case because the BPA91bHP29l2j6NPOldcpAvJCJBGk8oQFErfwuh93cxF8ajJJqBlVGqFcxMDEAc2LL2GKwmP86of49UgBTMycB5IdYergWRBETDNUrnzXX_55FgstCZiauPeD7MokIIPOFoOyW9vCRiBqZhlzLCuSnJ1ENFYtIh_PQ registration_id appears numerous times in the GCM JSON array - despite that same token only appearing once in my database.

So presumably there must be some other way of removing obsolete device tokens from my database??

And the reason I am concerned about this is because I have had the situation before (with iOS) where sending bad device tokens (to APNS) resulted in the push notification not being sent to valid devices, and I would obviously like to keep my database in a good state anyway.

I can't find anything to help on the web, so maybe I am missing or getting wrong something obvious?

ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253

1 Answers1

2

To know which registration token is causing this, you have to map to the same index in your registration_ids array of your request to GCM.

Here from the docs:

Results: Array of objects representing the status of the messages processed. The objects are listed in the same order as the request (i.e., for each registration ID in the request, its result is listed in the same index in the response).

joarleymoraes
  • 1,891
  • 14
  • 16
  • So, that *should* be the case. But, as mentioned in my question, that isn't what's happening... – ban-geoengineering May 05 '16 at 10:35
  • Are checking if there's at least one `canonical_id` in the GCM response ? If so then you should look for a `registration_id` inside the results array. – joarleymoraes May 05 '16 at 11:34
  • As you can see in the snippet in my question, the values of `canonical_ids` is `20,`. But look at the `results` array - the values of `registration_id` from the first two rows is identical - i.e., they do not correspond to the `registration_ids` that I *sent* to GCM. – ban-geoengineering May 05 '16 at 12:29
  • 1
    First of all, the `registration_id` inside `results` is NOT necessarily the same as the one from your request. It just tells you what's the current `canonical_id`. The fact that it's the same, means that you had two `registration_ids` in your request that maps to a single canonical_id (probably because they were generated by the same device). You should never rely on the registration_id received from the device and stored in your database; instead you should always replace it with canonical_id received from GCM (and make future requests with that id) – joarleymoraes May 05 '16 at 13:50
  • For anyone else needing a bit more clarification of `canonical_id` and `canonical_ids`, there is a good post here: http://stackoverflow.com/a/27073013/1617737 . :-) – ban-geoengineering May 15 '16 at 12:54
  • After just accepted your answer, I have noticed that the array I sent to GCM contained 944 token IDs. But the `results` array I got back from GCM has only 924 elements. The difference (20) is the same as the number of `canonical_ids` reported, but because of the mismatch in array lengths, I cannot simply map the indexes as you suggested... – ban-geoengineering May 15 '16 at 13:20