java GcmListenerService.onMessageReceived() 未调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31178029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GcmListenerService.onMessageReceived() not called
提问by Dan
I'm currently working on implementing GCM notifications into my app.
我目前正在将 GCM 通知实施到我的应用程序中。
The problem that I'm having is that the onMessageReceived()
method from my GcmListenerService
implementation isn't called. I receive the data from the GCM servers fine, since it automatically generates a notification (I wish to replace this with my own notification using the onMessageReceived()
method) but after that none of my log calls are printed in the log.
我遇到的问题是onMessageReceived()
我的GcmListenerService
实现中的方法没有被调用。我收到来自 GCM 服务器的数据很好,因为它会自动生成一个通知(我希望使用该onMessageReceived()
方法将其替换为我自己的通知),但之后我的日志调用都不会打印在日志中。
JSON that is sent from server to GCM server
从服务器发送到 GCM 服务器的 JSON
{
"notification" : {
"title" : "Title",
"text" : "Message",
"icon" : "@drawable\/ic_notification",
"click_action" : "OPEN_MAIN_ACTIVITY"
},
"registration_ids":[
"xxxx", "xxxx", "xxxx", "etc"
]
}
AndroidManifest.xml (GCM part only)
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 (just a quick print to see if its called at all)
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);
}
}
Not sure if the method to request tokens is relevant, but I can post it if needed.
不确定请求令牌的方法是否相关,但如果需要,我可以发布它。
If any part of the question is unclear, let me know, I'm not the best at explaining.
如果问题的任何部分不清楚,请告诉我,我不是最擅长解释的。
采纳答案by bitek
As explained in thisGithub issue which is exactly your problem:
From https://developers.google.com/cloud-messaging/server#notifications_and_data_messages"GCM will display the notification part on the client app's behalf. When optional data is provided, it is sent to the client app once user clicks on the notification and opens the client app. [...] On Android, data payload can be retrieved in the Intent used to launch your activity."
来自https://developers.google.com/cloud-messaging/server#notifications_and_data_messages“GCM 将代表客户端应用程序显示通知部分。当提供可选数据时,一旦用户点击通知,它就会发送到客户端应用程序并打开客户端应用程序。[...] 在 Android 上,可以在用于启动您的 Activity 的 Intent 中检索数据负载。”
So, the data is passed in the intent used to launch the activity, after the user taps on the notification. This means you need to do the following:
因此,在用户点击通知后,数据会在用于启动 Activity 的意图中传递。这意味着您需要执行以下操作:
Add a click_action to the notification key you send from the server: e.g.
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" }})
将 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" }})
See the reference for notification payload at: https://developers.google.com/cloud-messaging/server-ref#notification-payload-support
请参阅以下位置的通知有效负载参考:https: //developers.google.com/cloud-messaging/server-ref#notification-payload-support
In
AndroidManifest.xml
add an intent filter on the activity you want to be opened once the user clicks on the notification, with the same action name you used on the "click_action" key on the server side, e.g:<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>
Get the data from the intent on your onCreate()method oron onNewIntent()if you've set the launchMode to singleTop for the activity you want to launch when the notification is clicked, e.g:
@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); } }
在
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() ,如果你已经设置的launchMode到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); } }
I've tested this and can confirm that it works. (using XMPP connection)
我已经测试过了,可以确认它有效。(使用 XMPP 连接)
回答by Zephyr
The GcmListenerService.onMessageReceived() will not be called if the downstream message (json) contains a notification.
如果下游消息 (json) 包含通知,则不会调用 GcmListenerService.onMessageReceived()。
回答by Arthur Thompson
To receive the message in onMessageReceived you need to define the top level "data" field in your message object. The notification field is handled automatically and generates a notification, onMessageReceived does not get passed any of the data in the notification field.
要在 onMessageReceived 中接收消息,您需要在消息对象中定义顶级“数据”字段。通知字段会自动处理并生成通知,onMessageReceived 不会传递通知字段中的任何数据。
Update your message object to include a data field and onMessageReceived should be called:
更新您的消息对象以包含数据字段,并且应调用 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" ] }
回答by Sujit Yadav
onMessageReceived
called only for "data only" push massages.
onMessageReceived
仅调用“仅数据”推送按摩。