离子/科尔多瓦应用程序不会收到推送通知的背景 [英] Ionic/Cordova app doesn't receives push notification in the background

查看:237
本文介绍了离子/科尔多瓦应用程序不会收到推送通知的背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Andr​​oid应用程序不会受到后台推送通知,并应根据文档

  

在Android设备上的Andr​​oid应用程序并不需要运行   接收邮件。该系统将唤醒Android应用   通过当消息到达时,只要在意图的广播   应用程序建立与适当的广播接收机和   权限。

尝试不同的通知发现它确实接收推送通知而当且仅当该通知包含属性的消息下,如果没有,它只是将其丢弃它是封闭的。 (推送通知只是JSON对象)。

我的通知包含各类属性,包括警告,ID和称号,而只是消息让机器人来唤醒应用程序。

这是示例通知不能正常工作

  {事件:'消息',
  来自:947957531940,
  collapse_key:do_not_collapse,
  前景:真正的,
  有效载荷:
   {警告:Mensaje德Prueba',
     标题:TITULO Mensaje德Prueba'}}
 

这是示例通知的工作原理

  {事件:'消息',
  来自:947957531940,
  消息:Contenido德尔mensaje日prueba,
  collapse_key:do_not_collapse,
  前景:真正的,
  有效载荷:
   {警告:Mensaje德Prueba',
     标题:TITULO Mensaje德Prueba',
     消息:Contenido德尔mensaje日prueba。 }}
 

这是通过设计还是我做错了什么在我的应用程序?

一个Android标准

我的应用程序是使用离子与科尔多瓦开发的。

PD:对不起,我英文

编辑:

这是在app.js的。运行模块内部的Andr​​oid推code,如纳克-cordova 说明中规定:

 如果(ionic.Platform.isAndroid()){

  VAR androidConfig = {
    senderID:94 *************,
    欧洲央行:window.casosPush
  };

  尝试{
    VAR pushNotification = window.plugins.pushNotification;
  }赶上(前){

  }

  // Llamada恩卡索日EXITO
  VAR successfn =功能(结果){
    //警报(成功:+结果);
  };

  // Llamada恩卡索德错误
  VAR errorfn =功能(结果){
    window.alert(错误:+结果);
  };

  // Llamada德CASOS德notificacion推
  window.casosPush =功能(通知){
    开关(notification.event){
      案注册:
        如果(notification.regid.length大于0){
          $ rootScope.data.token = notification.regid;
          //警报(注册ID ='+ notification.regid);
        }
      打破;

      案消息:

        $ rootScope.mensajes.unshift(notification.payload);
        $ localstorage.setArray('mensajes',$ rootScope.mensajes);
        警报(JSON.stringify(通知));
      打破;

      案错误:
        警报(GCM误差='+ notification.msg);
      打破;

      默认:
        警报('未知GCM事件已发生');
      打破;
    }
  };
  尝试{

    // Llamada德registro骗子拉PLATAFORMA GCM
    pushNotification.register(successfn,errorfn,androidConfig);
  }赶上(通知){

  }
}
 

解决方案

在搜索计算器的所有问题,包括科尔多瓦/ PhoneGap的推送插件我找到了问题的根源去后。写在插件的源$ C ​​$ C,它不应该。

问题是,插件的源$ C ​​$ C要求的推送通知有才能触发通知而被放在后台消息字段。据especified在 GCMIntentService.java 文件。

 如果(extras.getString(信息)= NULL和放大器;!&安培;!extras.getString(信息)的长度()= 0){
    createNotification(背景下,临时演员);
}
 

最有用的职位是这答案这的问题的插件库。所以,因为我没有权力,我不能指定在推通知的消息字段中推送服务器的动作,我没有办法,只好重写源$ ​​C ​​$ C。

所以我改写了TE code是这样的:

  @覆盖
保护无效的onMessage(上下文的背景下,意图意图){
    Log.d(TAG的onMessage  - 背景:+上下文);

    //从信息中提取的有效载荷
    捆绑额外= intent.getExtras();
    如果(临时演员!= NULL)
    {
        //如果我们在前台,只是表面上的有效载荷,否则它发布到状态栏
        如果(PushPlugin.isInForeground()){
            extras.putBoolean(前台,真正的);
            PushPlugin.sendExtras(临时演员);
        }
        其他 {
            extras.putBoolean(前台,假);

            //发送通知,如果有消息
            //如果(extras.getString(消息)=&零安培;!&安培;!extras.getString(消息)的长度()= 0){
            如果(extras.getString(警告)= NULL和放大器;!&安培;!extras.getString(警报)的长度()= 0){
                createNotification(背景下,临时演员);
            }
        }
    }
}
 

这样的插件触发,如果它收到一个推送通知与田本地通知提醒,而不是信息。

于是,我改变了code本地通知本身:

 公共无效createNotification(上下文的背景下,捆绑演员)
{
        NotificationManager mNotificationManager =(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        字符串的appName = getAppName(本);

        意图notificationIntent =新的意图(这一点,PushHandlerActivity.class);
        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        notificationIntent.putExtra(pushBundle,临时演员);

        PendingIntent contentIntent = PendingIntent.getActivity(此,0,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);

        INT默认值= Notification.DEFAULT_ALL;

        如果(extras.getString(默认)!= NULL){
            尝试 {
                默认值=的Integer.parseInt(extras.getString(默认));
            }赶上(NumberFormatException异常E){}
        }

        NotificationCompat.Builder mBuilder =
            新NotificationCompat.Builder(上下文)
                .setDefaults(默认)
                .setSmallIcon(context.getApplicationInfo()。图标​​)
                .setWhen(System.currentTimeMillis的())
                //.setContentTitle(extras.getString("title))
                .setContentTitle(extras.getString(警告))
                //.setTicker(extras.getString("title))
                .setTicker(extras.getString(警告))
                .setContentIntent(co​​ntentIntent)
                .setAutoCancel(真正的);
    / *
        字符串消息= extras.getString(信息);
        如果(消息!= NULL){
            mBuilder.setContentText(消息);
        } 其他 {
            mBuilder.setContentText(<丢失邮件内容和GT;);
        }
    * /
    // Agregado mensaje predefinido
    mBuilder.setContentText(哈兹集团公司对更多资料);

        串msgcnt = extras.getString(msgcnt);
        如果(msgcnt!= NULL){
            mBuilder.setNumber(的Integer.parseInt(msgcnt));
        }

        INT notId = 0;

        尝试 {
            notId =的Integer.parseInt(extras.getString(notId));
        }
        赶上(NumberFormatException异常E){
            Log.e(TAG,数字格式异常 - 错误解析通告编号:+ e.getMessage());
        }
        赶上(例外五){
            Log.e(TAG,数字格式异常 - 错误解析通知ID+ e.getMessage());
        }

        mNotificationManager.notify((字符串)的appName,notId,mBuilder.build());
    }
 

现在在通知栏的通知将显示第一场警报,而不是所有权和第二A predefined消息,而不是场消息,这并不在我的推送通知存在。

然后我重新编译code有:

 离子平台RM机器人

离子平台添加的android

离子运行Android
 

所以孩子们,这是当你写一个插件适合所有人,但你不考虑一般情况下,你不记录以及发生的事情。该插件仅适用于人与外地消息和称号,在他们的推送通知是有用的。

我失去了我,因为这个实习两天,我把我的时间写这让其他人不会有。

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.

这篇关于离子/科尔多瓦应用程序不会收到推送通知的背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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