Background Push notifications on iOS issues


#1

Hi,

I am trying to implement background push notifications on iOS (Android works fine), I have trouble adding this peace of code


push.on('notification', function(data) {
    // do something with the push data
    // then call finish to let the OS know we are done
    push.finish(function() {
        console.log("processing of push data is finished");
    }, function() {
        console.log("something went wrong with push.finish for ID = " + data.additionalData.notId)
    }, data.additionalData.notId);
});

source: https://docs.ionic.io/services/push/

I inject the push into the constructor but still have some typescript issues:
"property ‘on’ does not exist on type ‘Push’"

I can’t send push notifications on iOS, I some kind of lost here


#2

Post the code please.


#3

Thank you for your reply, actually I am able to get notifications but using that push.on is not working because there is no “ON” method on push object.

this is my constructor and function, nothing fancy, I was testing before using it

import {
  Push,
  PushToken
} from '@ionic/cloud-angular';

constructor(public push: Push,
              public toastCtrl:ToastController ) {

    this.register();


  }

  private register(){

    this.push.register().then((t: PushToken) => {
      return this.push.saveToken(t);
    }).then((t: PushToken) => {

      console.log('Token saved:', t.token);

    }).catch( (error)=>{
        console.log("error push Register():" + JSON.stringify(error));
    })

    this.push.rx.notification()
      .subscribe((msg) => {
        alert(msg.title + ': ' + msg.text);

        this.toastCtrl.create({
          message: msg.title + ': ' + msg.text
        }).present();
     })


     this.push.on('notification', function(data) {
     
          console.log(data);
    
          // do something with the push data
          // then call finish to let the OS know we are done
          this.push.finish(function() {
              console.log("processing of push data is finished");
          }, function() {
              console.log("something went wrong with push.finish for ID = " + data.additionalData.notId)
          }, data.additionalData.notId);
      });


  }

#4

Yeah, I am also quite confused about the push.on in the Ionic Push docs. You too, because you already changed it to this.push.on. I think this is the actual source: https://github.com/driftyco/ionic-cloud/blob/master/src/push/push.ts with the event stuff here: https://github.com/driftyco/ionic-cloud/blob/master/src/push/push.ts#L294-L321

Just to make sure: You don’t have the Ionic Native “Push” shim (https://ionicframework.com/docs/native/push/) installed in your project, just the plain Cordova push plugin, right?


#5
  1. Instead of function() {} switch to () => {} for the callbacks on on and finish
  2. on is located at this.push.plugin.on, same goes for finish (this.push.plugin.finish)
  3. I believe the this.push.plugin.on(...) needs to be in the fulfilled Promise of this.push.register

I was messing with this just yesterday and today, exact same problems and these were my solutions

The docs are very vague on some of this stuff it seems :confused:


#6

Is there any way that you could post your code? I have to admit this is pretty confusing. I’m currently using this.push_ionic.rx.notification().subscribe(… to handle incoming messages, but that only seems to handle notifications with the app open.

However, SOMETHING is handling background notifications since they do indeed arrive. However, I can’t figure out how to run code when a background message comes in. (I’m trying to use the Badge library to update the launch icon badge on an incoming message)

Also, does Push need to be put as a provider in app.module?


#7

I can only agree, it’s quite confusing. If you want to actually perform an action when receiving (not tapping) a notification while the app is in the background, I don’t know the solution for that, because I haven’t needed it, sorry :confused: This is what works the best for me

app.component.ts

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { LocalNotifications } from '@ionic-native/local-notifications';
import { Push, PushToken } from '@ionic/cloud-angular';

@Component({
	templateUrl: 'app.html'
})
export class MyApp {
	private coldstartRedirect: boolean = false;

	constructor(
		private platform: Platform,
		private push: Push,
		private localNotifications: LocalNotifications
	) {}

	ngOnInit() {
		this.platform.ready().then(() => {
			/**
			 * Register for Push Notifications
			 */
			this.push.register().then((t: PushToken) => {
				return this.push.saveToken(t);
			}).then(
				(t: PushToken) => {
					if (this.platform.is("ios")) {
						/**
						 * Push Notifications
						 * Here we handle the click on a notification when the app is running
						 *
						 * The bit below only works for iOS and NOT Android, Android is handled
						 * in this.push.rx.notification
						 */
						this.localNotifications.on("click", (notification: LocalNotificationsNotification, state) => {
							this.handleNotificationClickMinimizedOpen(notification);
						});
					}
				},
				err => {
					console.error(err);
				}
			);
		});

		/**
		 * Push Notifications
		 * Here we handle the notifications from a COLDSTART
		 *
		 * this.coldstartRedirect is there to prevent multiple redirects.
		 * If there are multiple notifications, even though you only tap 1
		 * of them, the rest will eventually trigger this event as well.
		 */
		this.push.rx.notification().subscribe(notification => {
			if (notification.raw.additionalData.coldstart === true && this.coldstartRedirect === false) {
				this.handleNotificationClickColdstart(notification);
			} else if (this.platform.is("android")) {
				this.handleNotificationClickMinimizedOpen(notification);
			}
		});
	}

	handleNotificationClickColdstart(notification: GeneralNotification) {
		/**
		 * Perform actions depending on payload
		 * 
		 * If performing redirects, do
		 *     this.coldstartRedirect = true;
		 * to avoid multiple redirects, if multiple notifications are present on coldstart
		 */
	}

	handleNotificationClickMinimizedOpen(notification: GeneralNotification) {
		/**
		 * Perform actions depending on payload
		 */
	}
}

interface GeneralNotification {
	payload?: {
		[s: string]: any
	}
}

interface LocalNotificationsNotification {
	aps?: {
		alert: {
			title?: string,
			body?: string
		}
	},
	payload?: {
		[s: string]: any
	}
}

app.module.ts


import { Push } from '@ionic-native/push';

@NgModule({
	providers: [
		Push
	]
});

#8

ah… darn. Thanks. Yeah, my code is working how I would expect when the app is in the foreground. However, in the background I can’t get it to properly fire. I’m trying to increase the badge number when a message comes in… but it’s proving to be quite difficult.


#9

The way I would do that would be to set the badge number with the notification, so if you’re using the API set this:

notification: {
    ios: {
        badge: 1234
    }
}

Just bear in mind this sets the value to the number provided, it doesn’t increase by the number provided… So you would have to check server-side if the user has other things that should increase the number, whiiich is can be a bit of a hassle :confused:


#10

I’m using push from ionic cloud services. Therefore, I’m kind of at their mercy as far as server side goes. My work-around up until this point is to send a “badge: 1” whenever I send out a push notification so that the user knows that something is up. However, there doesn’t seem to be a way to query the number easily from their server.

I assumed there would be something more straightforward… although talking about it with you has given me an idea. :slight_smile:

So, Thanks!


#11

Hey… I got it working and I thought I’d share a little of what I did to help the poor sap that has to follow in my footsteps.

mich356c, I ended up using the method you suggested for background push notifications that increment the launch icon badge.

In my database, I created a ‘badge’ field for each username that keeps track of the number of badges that should be displayed on a given users launch icon.

When I create a new notification from user1 to user2:

  • I query user2’s badge current number. (initialized to zero)
  • I use that number in the http call with the message info suggested by mich256c
notification: {
    ios: {
        badge: user2 current badge number + 1
    }
}
  • I then write to the database for user2’s badge field to insert the updated (+1) number.

Then, while user2 is using the programs, I do book-keeping to update the badge ID as so:

  • When I need to clear the badges when user2 views the message (like with an entry to a “messages” page) I clear user2’s badge using badge in ionic-native (https://ionicframework.com/docs/native/badge/) badge.clear() method and write a zero to user2’s database badge field.
  • If something happens that requires the badge to change for reasons not associated with an incoming notification, I use badge.get() and badge.set() to control what user2 sees, and then I write that value to the database.

I would MUCH prefer to be able to write code that sees an incoming background push notification and just uses badge.increase(1)… but I’m starting to think this is impossible. (I would love to be proved wrong, though!)

Thanks again for the push in the right direction.