当应用程序处于后台或手机处于锁定状态或处于睡眠模式但触发通知时,不会调用GcmListenerService。如何调用它 当App处于前台时,它理想地工作。 GcmListenerService的代码如下:
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
LocalDataBaseManager mDbManager;
String message;
Random randomNumber;
long ID;
/**
* Called when message is received.
*
* @param from SenderID of the sender.
* @param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
@Override
public void onMessageReceived(String from, Bundle data) {
String message ;
String title;
// ID = Utils.getIDForPush("pushId",this);
// if(ID == 0){
// ID = 1;
// }else {
// ID += 1;
// }
// Utils.saveIDForPush("pushId",ID,this);
Bundle bundle = data.getBundle("notification");
if(bundle!= null){
message = bundle.getString("body");
title = bundle.getString("title");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);}
else {
message ="";
title = "NCMS";
}
mDbManager = LocalDataBaseManager.getInstance(this);
if (from.startsWith("/topics/")) {
Calendar c = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss");
String format = s.format(new Date());
ID = Long.parseLong(format);
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date());
Warnings warnings = new Warnings();
warnings.setWARNING_ID(ID);
warnings.setWARNING_EN(message);
warnings.setWARNING_AR(message);
warnings.setSTART_DATE_TIME(date);
warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH));
warnings.setSEVERITY("");
warnings.setEND_DATE_TIME("");
warnings.setUPDATE_NO("");
mDbManager.insertNotificationInfo(warnings);
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
// KeyguardManager km = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
// boolean locked = km.inKeyguardRestrictedInputMode();
//
// String release = android.os.Build.VERSION.RELEASE;
//
//
// if (Integer.parseInt(String.valueOf(release.charAt(0))) < 5 && locked) {
//
// this.stopService(new Intent(this, NotificationService.class));
// Intent serviceIntent = new Intent(this, NotificationService.class);
// this.startService(serviceIntent);
//
// }
sendNotification(title,message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String title,String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("message",message);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ncms_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
此服务的清单信息如下:
<service
android:name=".gcm.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
我在这里缺少什么。
答案 0 :(得分:32)
看来这个问题的核心实际上是服务器端问题。如果服务器正在发送通知消息,则如果应用程序在后台,则不会调用onMessageReceived
。服务器实际上应该发送 data 消息。
GCM Docs讨论差异。
基本上,消息的有效负载应该有data
密钥,例如
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data" : {
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
}
而不是通知键,例如
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
}
}
更具体地说,GCM文档说明发送的邮件(包括数据和通知有效负载)将根据应用程序是在前台还是后台进行区分:< / p>
接收包含通知和数据有效负载的消息时的应用行为取决于应用是在后台还是前景 - 基本上是否在接收时处于活动状态。
- 在后台,应用会在通知托盘中收到通知有效负载,并仅在用户点击通知时处理数据有效负载。
- 当您在前台时,您的应用会收到一个包含两个有效负载的捆绑包。
This github thread也有一个很好的解释:
因此有两种GCM消息:
通知消息 - 这些消息旨在生成通知,而不会由应用程序进行中间处理。如果应用程序正在运行,它们只会触发onMessageReceived。
数据消息 - 这些消息旨在以静默方式将数据传递到应用程序的消息服务。即使应用程序在后台,它们也会点击onMessageReceived。然后,该服务可以选择使用普通系统通知API生成通知,也可以选择以静默方式处理该消息。
答案 1 :(得分:12)
我面临的问题是,当Application处于后台或强制关闭时,会触发通知,但不是通过GcmListenService而是通过GCMReceiver 因此,当应用程序处于前台或后台或强制终止时,我扩展了GCMReceiver并使其成为这样的。它会被称为 修改后的GCMListenerService如下:
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
LocalDataBaseManager mDbManager;
String message;
Random randomNumber;
long ID;
/**
* Called when message is received.
*
* @param from SenderID of the sender.
* @param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
@Override
public void onMessageReceived(String from, Bundle data) {
String message ;
String title;
// ID = Utils.getIDForPush("pushId",this);
// if(ID == 0){
// ID = 1;
// }else {
// ID += 1;
// }
// Utils.saveIDForPush("pushId",ID,this);
Bundle bundle = data.getBundle("notification");
if(bundle!= null){
message = bundle.getString("body");
title = bundle.getString("title");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);}
else {
message ="";
title = "NCMS";
}
mDbManager = LocalDataBaseManager.getInstance(this);
if (from.startsWith("/topics/")) {
Calendar c = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss");
String format = s.format(new Date());
ID = Long.parseLong(format);
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date());
Warnings warnings = new Warnings();
warnings.setWARNING_ID(ID);
warnings.setWARNING_EN(message);
warnings.setWARNING_AR(message);
warnings.setSTART_DATE_TIME(date);
warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH));
warnings.setSEVERITY("");
warnings.setEND_DATE_TIME("");
warnings.setUPDATE_NO("");
mDbManager.insertNotificationInfo(warnings);
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
// KeyguardManager km = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
// boolean locked = km.inKeyguardRestrictedInputMode();
//
// String release = android.os.Build.VERSION.RELEASE;
//
//
// if (Integer.parseInt(String.valueOf(release.charAt(0))) < 5 && locked) {
//
// this.stopService(new Intent(this, NotificationService.class));
// Intent serviceIntent = new Intent(this, NotificationService.class);
// this.startService(serviceIntent);
//
// }
sendNotification(title,message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* @param message GCM message received.
*/
private void sendNotification(String title,String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("message",message);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ncms_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
和GCM Receiver如下
public class GcmBroadcastReceiver extends GcmReceiver {
LocalDataBaseManager mDbManager;
@Override
public void onReceive(Context context, Intent intent) {
mDbManager = LocalDataBaseManager.getInstance(context);
Bundle bundle = intent.getExtras();
bundle.keySet();
Set<String> keySet = bundle.keySet();
if(keySet != null && keySet.isEmpty() == false) {
Iterator<String> it = keySet.iterator();
int i = 0;
while(it.hasNext()){
String key = it.next();
String desc = bundle.getString(key);
Log.d("BroadCast Values",key +" "+desc);
}
}
Log.d("", "In Receive Method of Broadcast Receiver");
if (bundle != null && bundle.containsKey("gcm.notification.body")) {
String message = bundle.getString("gcm.notification.body","");
Long ID = new Date().getTime();
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date());
Warnings warnings = new Warnings();
warnings.setWARNING_ID(ID);
warnings.setWARNING_EN(message);
warnings.setWARNING_AR(message);
warnings.setSTART_DATE_TIME(date);
warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH));
warnings.setSEVERITY("");
warnings.setEND_DATE_TIME("");
warnings.setUPDATE_NO("");
mDbManager.insertNotificationInfo(warnings);
// message received from some topic.
}
super.onReceive(context, intent);
// ComponentName cn = new ComponentName(context.getPackageName(), RegistrationIntentService.class.getName());
// startWakefulService(context, intent.setComponent(cn));
// setResultCode(Activity.RESULT_OK);
}
}
GCMReceiver的清单更改正在关注
<receiver
android:name=".gcm.GcmBroadcastReceiver"
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.uae.ncms" />
</intent-filter>
</receiver>
<service
android:name=".gcm.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>