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

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

问题描述

我的 Android 应用在后台没有收到推送通知,它应该根据 文档.

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

Android 设备上的 Android 应用程序不需要运行来接收消息.系统会唤醒Android应用当消息到达时通过 Intent 广播,只要应用程序设置了适当的广播接收器和权限.

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.

尝试不同的通知发现当且仅当通知包含属性 "message" 时,它确实会在关闭时收到推送通知,否则,它只会丢弃它.(推送通知只是 JSON 对象).

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

我的通知包含各种属性,包括alert"、id"和title",但只有message"才能让 Android 唤醒应用.

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

不起作用的示例通知:

{ 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 设计的标准还是我在我的应用中做错了什么?

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

我的应用是使用 Ionic 和 Cordova 开发的.

My app was developed using Ionic with Cordova.

PD:请原谅我的英语.

PD: Excuse my english.

这是app.js中.run模块内的Android推送代码,如ng-cordova 指令指定:

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

  }
}

推荐答案

在 stackoverflow 中搜索所有涉及 Cordova/Phonegap Push Plugin 的问题后,我找到了问题的根源.插件的源代码里写的,应该不是.

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.

问题是插件源代码要求推送通知具有消息"字段,以便在后台触发通知.它在 GCMIntentService.java 文件中指定.

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

最有用的帖子是这个 answer 和这个 issue 在插件库中.因此,由于我无法控制推送服务器操作,因此无法在推送通知中指定消息"字段,因此我别无选择,只能重写源代码.

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天全站免登陆