[英]Ionic/Cordova app doesn't receives push notification in the background
我的Android應用程序在后台沒有收到推送通知,它應該根據文檔 。
Android設備上的Android應用程序無需運行即可接收消息。 只要應用程序設置了正確的廣播接收器和權限,系統就會在消息到達時通過Intent廣播喚醒Android應用程序。
嘗試不同的通知發現它確實在關閉時收到推送通知,當且僅當通知包含屬性“message”時 ,如果沒有,它只是丟棄它。 (推送通知只是JSON對象)。
我的通知包含所有類型的屬性,包括“alert”,“id”和“title”,但只有“message”才能讓Android喚醒應用。
示例通知不起作用 :
{ event: 'message',
from: '947957531940',
collapse_key: 'do_not_collapse',
foreground: true,
payload:
{ alert: 'Mensaje de Prueba',
title: 'Titulo Mensaje de Prueba' } }
例如通知的工作原理 :
{ event: 'message',
from: '947957531940',
message: 'Contenido del mensaje de prueba.',
collapse_key: 'do_not_collapse',
foreground: true,
payload:
{ alert: 'Mensaje de Prueba',
title: 'Titulo Mensaje de Prueba',
message: 'Contenido del mensaje de prueba.' } }
這是Android標准設計還是我在我的應用程序中做錯了什么?
我的應用程序是使用Ionic與Cordova開發的。
PD:請原諒我的英語。
編輯:
這是app.js中.run模塊內的Android推送代碼,因為ng-cordova指令指定:
if (ionic.Platform.isAndroid()){
var androidConfig = {
"senderID": "94*************",
"ecb": "window.casosPush"
};
try{
var pushNotification = window.plugins.pushNotification;
} catch (ex){
}
// Llamada en caso de exito
var successfn = function(result){
//alert("Success: " + result);
};
// Llamada en caso de error
var errorfn = function(result){
window.alert("Error: " + result);
};
// Llamada de casos de notificacion push
window.casosPush = function(notification){
switch (notification.event){
case 'registered':
if (notification.regid.length > 0){
$rootScope.data.token = notification.regid;
//alert('registration ID = ' + notification.regid);
}
break;
case 'message':
$rootScope.mensajes.unshift(notification.payload);
$localstorage.setArray('mensajes', $rootScope.mensajes);
alert(JSON.stringify(notification));
break;
case 'error':
alert('GCM error = ' + notification.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
};
try{
// Llamada de registro con la plataforma GCM
pushNotification.register(successfn,errorfn,androidConfig);
} catch(notification){
}
}
在涉及Cordova / Phonegap推送插件的stackoverflow中搜索所有問題后,我找到了問題的來源。 寫在插件的源代碼中,它不應該。
問題是插件源代碼要求推送通知具有“消息”字段,以便在后台觸發通知。 它在GCMIntentService.java文件中指定。
if (extras.getString("message") != null && extras.getString("message").length() != 0) {
createNotification(context, extras);
}
最有幫助的帖子是這個答案和插件存儲庫中的這個問題 。 所以,因為我沒有權力推送服務器操作,我無法在推送通知中指定“消息”字段,我別無選擇,只能重寫源代碼。
所以我重寫了這樣的代碼:
@Override
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
Bundle extras = intent.getExtras();
if (extras != null)
{
// if we are in the foreground, just surface the payload, else post it to the statusbar
if (PushPlugin.isInForeground()) {
extras.putBoolean("foreground", true);
PushPlugin.sendExtras(extras);
}
else {
extras.putBoolean("foreground", false);
// Send a notification if there is a message
//if (extras.getString("message") != null && extras.getString("message").length() != 0) {
if (extras.getString("alert") != null && extras.getString("alert").length() != 0) {
createNotification(context, extras);
}
}
}
}
這樣,如果插件收到帶有“alert”字段而不是“message”字段的推送通知,則會觸發本地通知。
然后,我更改了本地通知本身的代碼:
public void createNotification(Context context, Bundle extras)
{
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String appName = getAppName(this);
Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("pushBundle", extras);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
int defaults = Notification.DEFAULT_ALL;
if (extras.getString("defaults") != null) {
try {
defaults = Integer.parseInt(extras.getString("defaults"));
} catch (NumberFormatException e) {}
}
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setDefaults(defaults)
.setSmallIcon(context.getApplicationInfo().icon)
.setWhen(System.currentTimeMillis())
//.setContentTitle(extras.getString("title"))
.setContentTitle(extras.getString("alert"))
//.setTicker(extras.getString("title"))
.setTicker(extras.getString("alert"))
.setContentIntent(contentIntent)
.setAutoCancel(true);
/*
String message = extras.getString("message");
if (message != null) {
mBuilder.setContentText(message);
} else {
mBuilder.setContentText("<missing message content>");
}
*/
// Agregado mensaje predefinido
mBuilder.setContentText("Haz clic para más información");
String msgcnt = extras.getString("msgcnt");
if (msgcnt != null) {
mBuilder.setNumber(Integer.parseInt(msgcnt));
}
int notId = 0;
try {
notId = Integer.parseInt(extras.getString("notId"));
}
catch(NumberFormatException e) {
Log.e(TAG, "Number format exception - Error parsing Notification ID: " + e.getMessage());
}
catch(Exception e) {
Log.e(TAG, "Number format exception - Error parsing Notification ID" + e.getMessage());
}
mNotificationManager.notify((String) appName, notId, mBuilder.build());
}
現在,通知欄中的通知將首先顯示字段“alert”而不是“title”,其次是預定義消息,而不是我的推送通知中不存在的字段“message”。
然后我只需重新編譯代碼:
ionic platform rm android
ionic platform add android
ionic run android
所以孩子們,這就是當你為每個人寫一個插件時會發生什么,但你不考慮通用案例,而且你沒有很好地記錄。 該插件僅對推送通知中包含“消息”和“標題”字段的用戶有用。
因為這個原因,我失去了兩天的實習機會,我花了很多時間寫這篇文章,以便其他人不必這樣做。
你是對的@David prieto。 問題是插件源代碼要求推送通知具有“消息”字段,以便在后台觸發通知。
有一種方法可以將“消息”字段放在推送通知中並且簡單。 具有通知數據的有效載荷數組,通過API發送。 它應該有一個“消息”字段。 因此推送通知將自動在其中包含一個消息字段,它將在后台和前台檢測到。
我有同樣的問題,我通過更改一些代碼行解決了。 我使用了phonegap-plugin-push插件並更改了這個文件。(僅適用於android平台)
插件文件夾 : phonegap-plugin-push / src / android / com / adobe / phonegap / push / FCMService.java
平台文件夾 : android / src / com / adobe / phonegap / push / FCMService.java
您需要更改兩個文件中的一個,這取決於您是否已添加平台。
// if we are in the foreground and forceShow is `false` only send data
if (!forceShow && PushPlugin.isInForeground()) {
Log.d(LOG_TAG, "foreground");
extras.putBoolean(FOREGROUND, true);
extras.putBoolean(COLDSTART, false);
PushPlugin.sendExtras(extras);
}
// if we are in the foreground and forceShow is `true`, force show the notification
if the data has at least a message or title
else if (forceShow && PushPlugin.isInForeground()) {
Log.d(LOG_TAG, "foreground force");
extras.putBoolean(FOREGROUND, true);
extras.putBoolean(COLDSTART, false);
showNotificationIfPossible(applicationContext, extras);
}
// if we are not in the foreground always send notification if the data has at least a message or title
else {
Log.d(LOG_TAG, "background");
extras.putBoolean(FOREGROUND, false);
extras.putBoolean(COLDSTART, PushPlugin.isActive());
showNotificationIfPossible(applicationContext, extras);
}
這里,PushPlugin.sendExtras(),這是localNotification的觸發器,showNotificationIfPossible()是電話通知的觸發器。
所以我改變了這樣的代碼。
// if we are in the foreground and forceShow is `false` only send data
if (!forceShow && PushPlugin.isInForeground()) {
Log.d(LOG_TAG, "foreground");
extras.putBoolean(FOREGROUND, true);
extras.putBoolean(COLDSTART, false);
//PushPlugin.sendExtras(extras); // commented }
// if we are in the foreground and forceShow is `true`, force show the notification if the data has at least a message or title
else if (forceShow && PushPlugin.isInForeground()) {
Log.d(LOG_TAG, "foreground force");
extras.putBoolean(FOREGROUND, true);
extras.putBoolean(COLDSTART, false);
//showNotificationIfPossible(applicationContext, extras);// commented }
// if we are not in the foreground always send notification if the data has at least a message or title
else {
Log.d(LOG_TAG, "background");
extras.putBoolean(FOREGROUND, false);
extras.putBoolean(COLDSTART, PushPlugin.isActive());
//showNotificationIfPossible(applicationContext, extras); // commented
}
PushPlugin.sendExtras(extras); //added
所以我可以根據需要獲取通知並使用localNotification插件處理它。 希望這會幫助你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.