gcm работает на эмуляторе, но выдает canonical_ids»: 0 на моем устройстве

#android #google-cloud-messaging

#Android #google-облако-обмен сообщениями

Вопрос:

Когда я отправляю push-уведомление на эмулятор, я получаю это сообщение:

 {"multicast_id":8595716062607030073,"success":1,"failure":0,"canonical_ids":1,"results":            [{"message_id":"0:1403002114354553Df16b55f9fd7ecd","registration_id":"XXXXXXX...
  

Но после регистрации и отправки уведомления на мое устройство с новым идентификатором я получаю это :

 {"multicast_id":8356469968000736599,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1403002260325568Df16b55f9fd7ecd"}]}
  

Я активировал уведомление на своем телефоне и подключился к учетной записи Google
Также я получаю новый регистрационный идентификатор в своей базе данных при регистрации, но я не могу понять проблему
Вот мой manifest.xml:

    <!-- for gcm -->
    <receiver                        
        android:name="com.test.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="com.test.android.gcm" />
        </intent-filter>
    </receiver>

    <service android:name="com.test.android.gcm.GCMNotificationIntentService" />
    <!-- end for gcm -->
    <!-- GCM activity -->
    <activity
        android:name="com.test.android.gcm.RegisterActivity"
        android:label="@string/app_name" >
    </activity>
    <activity
        android:name="com.test.android.gcm.MainActivity"
        android:configChanges="orientation|keyboardHidden"
        android:label="@string/app_name" >
    </activity>
    <!-- End GCM activity -->
  

Может кто-нибудь указать мне правильное направление, пожалуйста

Комментарии:

1. Ваш вопрос неясен. Вы используете эмулятор или устройство? Вы когда-нибудь видели уведомление на устройстве / эмуляторе? Если нет, пожалуйста, отправьте свой код (GCMNotificationIntentService, GcmBroadcastReceiver и полный манифест).

Ответ №1:

Вот как это работает.

При регистрации клиента в GCM вы получаете регистрационный идентификатор. Назовем это A. Ваш сервер сохранит это, чтобы он мог отправлять уведомления.

Время идет, и по какой-либо причине, скажем, по истечении срока действия регистрационного идентификатора на сервере GCM, GCM решает предоставить тому же клиенту другой, более новый идентификатор. Мы назовем его B. Ваш сервер тоже поддерживает его.

Теперь у вас должны быть идентификаторы для одного и того же устройства, одно старое, а другое обновленное. Они оба будут действительны для отправки уведомлений.

В многоадресном результате получение канонического идентификатора означает, что используемый вами идентификатор не является самым последним идентификатором. Когда вы получаете канонический идентификатор, он должен заменить тот, который вы используете (поскольку это самый актуальный идентификатор).

Для A вы получите многоадресный результат с успехом = 1, канонический идентификатор = B. Для B вы просто получите success = 1, потому что это самый последний идентификатор. Ответ для A указывает, что он устарел и должен быть заменен на B.

Поскольку в вашем случае вы используете недавно зарегистрированный идентификатор (как вы сказали), нет причин для его устаревания, и с вашим кодом проблем нет.

Что касается того, почему вы не получаете уведомление, у вашего клиента должен быть класс получателя, который расширяет WakefulBroadcastReceiver и обрабатывает входящее уведомление:

 public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Explicitly specify that GcmIntentService will handle the intent.
        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}
  

и IntentService для полноты картины

`общедоступный класс GCMIntentService расширяет IntentService { общедоступный статический конечный int NOTIFICATION_ID = 1; частный NotificationManager mNotificationManager; NotificationCompat.Builder builder;

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

@Override
protected void onHandleIntent(Intent intent) {
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    // The getMessageType() intent parameter must be the intent you received
    // in your BroadcastReceiver.
    String messageType = gcm.getMessageType(intent);

    if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
        /*
         * Filter messages based on message type. Since it is likely that GCM
         * will be extended in the future with new message types, just ignore
         * any message types you're not interested in, or that you don't
         * recognize.
         */
        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());
        // If it's a regular GCM message, do some work.
        } else if (GoogleCloudMessaging.
                MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            // This loop represents the service doing some work.
            for (int i=0; i<5; i  ) {
                Log.i(TAG, "Working... "   (i 1)
                          "/5 @ "   SystemClock.elapsedRealtime());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
            }
            Log.i(TAG, "Completed work @ "   SystemClock.elapsedRealtime());
            // Post notification of received message.
            sendNotification("Received: "   extras.toString());
            Log.i(TAG, "Received: "   extras.toString());
        }
    }
    // Release the wake lock provided by the WakefulBroadcastReceiver.
    GcmBroadcastReceiver.completeWakefulIntent(intent);
}

// Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(String msg) {
    mNotificationManager = (NotificationManager)
            this.getSystemService(Context.NOTIFICATION_SERVICE);

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

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

    mBuilder.setContentIntent(contentIntent);
    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    }
}
  

См. раздел Реализация клиента GCM.

Комментарии:

1. Извините, но я новичок в GCM, поэтому я не совсем понял ваш ответ (когда вы говорите об идентификаторе, вы имеете в виду регистрационный идентификатор?), Можете ли вы сказать мне, что именно я могу сделать, чтобы решить эту проблему или где моя проблема

2. Во-первых, проблем нет. Такое поведение ожидается.

3. Во-вторых, я обновил свой ответ. Не забудьте принять его, если это вам поможет. 🙂

4. Это помогло мне разобраться в процессе, но я все равно не получаю уведомления на своем устройстве

5. Это совершенно другая проблема. Вам нужен класс, который расширяется WakefulBroadcastReceiver в вашем клиенте. Смотрите developer.android.com/google/gcm/client.html . Пожалуйста, примите ответ, поскольку он полностью отвечает на ваш вопрос.