GcmListenerService.onMessageReceived() не вызывается
В настоящее время я работаю над внедрением уведомлений GCM в свое приложение.
Проблема, с которой я сталкиваюсь, заключается в том, что метод onMessageReceived()
из моей реализации GcmListenerService
не вызывается. Я получаю данные с серверов GCM в порядке, так как он автоматически генерирует уведомление (я хочу заменить это своим собственным уведомлением с помощью метода onMessageReceived()
), но после этого ни один из моих вызовов журнала не печатается в журнале.
JSON, отправленный с сервера на сервер GCM
{
"notification" : {
"title" : "Title",
"text" : "Message",
"icon" : "@drawable\/ic_notification",
"click_action" : "OPEN_MAIN_ACTIVITY"
},
"registration_ids":[
"xxxx", "xxxx", "xxxx", "etc"
]
}
AndroidManifest.xml(только часть GCM)
<!-- GCM START -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.my.package" />
</intent-filter>
</receiver>
<service
android:name=".Services.ListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".Services.IDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<!-- GCM END -->
GcmListenerService (просто быстрый отпечаток, чтобы увидеть, вызвано ли его вообще)
public class ListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
@Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("title");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
}
}
Не уверен, что метод запроса токенов релевантен, но я могу опубликовать его, если это необходимо.
Если какая-либо часть вопроса неясна, дайте мне знать, я не лучше объясню.
Ответы
Ответ 1
Как объяснено в этой > проблеме Github, которая является именно вашей проблемой:
От https://developers.google.com/cloud-messaging/server#notifications_and_data_messages
"GCM отобразит часть уведомления в имени клиентских приложений. Когда предоставляются дополнительные данные, она отправляется клиентскому приложению, когда пользователь нажимает на уведомление и открывает клиентское приложение.
[...] В Android, полезная нагрузка данных может быть получена в намерении, используемом для запуска вашей активности. "
Таким образом, данные передаются в намерении, используемом для запуска активности, после того, как пользователь нажимает на уведомление.
Это означает, что вам нужно сделать следующее:
-
Добавить click_action к уведомляющему ключу, отправленному с сервера:
например
send_queue.append({'to': REGISTRATION_ID,
'message_id': random_id(),
"notification" : {
"body" : "Hello from Server! What is going on? Seems to work!!!",
"title" : "Hello from Server!",
"icon" : "@drawable/ic_school_white_48dp",
"sound": "default",
"color": "#03A9F4",
"click_action": "OPEN_MAIN_ACTIVITY"
},
'data': { 'message': "Hello" }})
См. ссылку на полезную нагрузку уведомления по адресу: https://developers.google.com/cloud-messaging/server-ref#notification-payload-support
-
В AndroidManifest.xml
добавьте фильтр намерений в действие, которое вы хотите открыть, как только пользователь нажмет на уведомление, с тем же именем действия, которое вы использовали на клавише click_action на стороне сервера, например:
<activity
android:name=".ui.MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="OPEN_MAIN_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
-
Получите данные из намерения в методе onCreate() или в onNewIntent(), если вы установили startMode на singleTop для активности, которую вы хотите запустить при нажатии на уведомление, например:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent.hasExtra(Constants.KEY_MESSAGE_TXT)) {
String message = intent.getStringExtra(Constants.KEY_MESSAGE_TXT);
Log.d(TAG, message);
}
}
Я тестировал это и могу подтвердить, что он работает. (с использованием соединения XMPP)
Ответ 2
GcmListenerService.onMessageReceived() не будет вызываться, если входящее сообщение (json) содержит уведомление.
Ответ 3
Чтобы получить сообщение в onMessageReceived, вам необходимо определить поле "данные" верхнего уровня в вашем объекте сообщения. Поле уведомлений обрабатывается автоматически и генерирует уведомление, onMessageReceived не получает никаких данных в поле уведомления.
Обновите свой объект сообщения, чтобы включить поле данных, и onMessageReceived следует вызвать:
{
"notification" : {
"title" : "Title",
"text" : "Message",
"icon" : "@drawable\/ic_notification",
"click_action" : "OPEN_MAIN_ACTIVITY"
},
"data": {
"some_key": "some_value"
},
"registration_ids":[
"xxxx", "xxxx", "xxxx", "etc"
]
}
Ответ 4
onMessageReceived
, вызываемый только для массажа "только данные".