Ionic / Cordova应用程序在后台不接收推送通知 [英] Ionic/Cordova app doesn't receives push notification in the background

查看:3207
本文介绍了Ionic / Cordova应用程序在后台不接收推送通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Android应用程式在后台不接收推播通知,而且应该根据文件< a>。


Android设备上的Android应用程序不需要运行
接收消息。系统将在消息到达时通过Intent广播唤醒Android应用程序
,只要
应用程序设置了正确的广播接收器和
权限。


尝试不同的通知发现,当且仅当通知包含属性message ,如果没有,它只是丢弃它。 (推送通知只是JSON对象)。



我的通知包含所有类型的属性,包括alert,id和title,但只有message

$

pre> {event:'message',
来自:'947957531940',
collapse_key:'do_not_collapse',
foreground:true,
有效负载:
{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,

{alert:'Mensaje de Prueba',
title:'Titulo Mensaje de Prueba',
message:'Contenido del mensaje de prueba。'}}



这是Android设计的标准,还是我的应用程序出错了?



我的应用程式是使用Ionic与Cordova共同开发的。



PD:不要使用英语。



EDIT:



这是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){

}

// libamada en caso de exito
var successfn = function(result){
// alert(Success:+ result);
};

//内存错误
var errorfn = function(result){
window.alert(Error:+ result);
};

//通过
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;

默认值:
alert('发生未知的GCM事件');
break;
}
};
try {

//注册表格GCM
pushNotification.register(successfn,errorfn,androidConfig);
} catch(notification){

}
}




问题是插件源代码需要推送通知有message字段在后台触发通知的命令。它在 GCMIntentService.java 文件中指定。

  if(extras.getString(message )!= null&& extras.getString(message)length()!= 0){
createNotification(context,extras);
}

最有用的帖子是 answer 和此问题 。所以,因为我没有权力推送服务器动作,我不能在推送通知中指定一个消息字段,我别无选择,只能重写源代码。



所以我重写了这样的代码:

  @Override 
protected void onMessage intent){
Log.d(TAG,onMessage - context:+ context);

//从消息中提取有效负载
Bundle extras = intent.getExtras();
if(extras!= null)
{
//如果我们在前台,只是表面的有效负载,否则发布到状态栏
if(PushPlugin.isInForeground )){
extras.putBoolean(foreground,true);
PushPlugin.sendExtras(extras);
}
else {
extras.putBoolean(foreground,false);

//如果有消息,发送通知
// if(extras.getString(message)!= null&& extras.getString(message)。 length()!= 0){
if(extras.getString(alert)!= null&& extras.getString(alert)。 createNotification(context,extras);
}
}
}
}

方式插件触发一个本地通知,如果它收到一个推送通知与字段警报,而不是消息。



然后,我更改了本地通知本身:

  public void createNotification(Context context,Bundle extras)
{
NotificationManager mNotificationManager = )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
.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 paramásinformació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,数字格式异常 - 错误解析通知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字段。



然后我只是重新编译代码: / p>

 离子平台rm android 

离子平台添加android

离子运行android

所以孩子们,这是当你为每个人写一个插件,但你不考虑通用案例,你没有很好地记录。该插件仅对推送通知中包含message和title字段的人有用。



我失去了两天的实习,我的时间写这个,所以其他人不必。


My Android app doesn't receive push notifications in the background and it should according to the documentation.

An Android application on an Android device doesn't need to be running to receive messages. The system will wake up the Android application via Intent broadcast when the message arrives, as long as the application is set up with the proper broadcast receiver and permissions.

Trying different notifications discovered that it does receives the push notifications while it is closed if and only if the notifications contains the attribute "message", if not, it just discards it. (Push notifications are just JSON objects).

My notifications contain all kind of attributes including "alert", "id" and "title", but only "message" makes Android to wake up the app.

Example notification that doesn't work:

{ event: 'message',
  from: '947957531940',
  collapse_key: 'do_not_collapse',
  foreground: true,
  payload: 
   { alert: 'Mensaje de Prueba',
     title: 'Titulo Mensaje de Prueba' } }

Example notification that works:

{ 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.' } }

Is this an Android standard by design or am I doing something wrong in my app?

My app was developed using Ionic with Cordova.

PD: Excuse my english.

EDIT:

This is the Android push code inside the .run module in app.js, as ng-cordova instructions specify:

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){

  }
}

解决方案

After searching all questions in stackoverflow involving Cordova/Phonegap Push Plugin I found de source of the problem. Is written in the source code of the plugin, and it shouldn't.

The problem was that the plugin source code requires the push notification to have "message" field in order to trigger a notification while being on the background. It is especified in the GCMIntentService.java file.

if (extras.getString("message") != null && extras.getString("message").length() != 0) {
    createNotification(context, extras);
}

The most helpful posts are this answer and this issue in the plugin repository. So, because I have no power over the push server action I can't have specified a "message" field in the push notifications, I had no alternative but to rewrite the source code.

So I rewrote te code like this:

@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);
            }
        }
    }
}

That way the plugin triggers a local notification if it receives a push notifications with the field "alert" instead of "message".

Then, I changed the code for the local notification itself:

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());
    }

Now the notification in the notification bar will show first the field "alert" instead of "title" and second a predefined message instead of the field "message" that doesn't exist in my push notifications.

Then I just recompile the code with:

ionic platform rm android

ionic platform add android

ionic run android

So kids, this is what happens when you write a plugin for everyone but you don't consider generic cases and you don't document well. That plugin is only useful for people with the field "message" and "title" in their push notifications.

I lost two days of my internship because of this, I took my time to write this so others won't have to.

这篇关于Ionic / Cordova应用程序在后台不接收推送通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆