vapor / apns

Helpful extensions and abstractions for using APNSwift
MIT License
115 stars 30 forks source link

Can't send "contentAvailable" on it's own #39

Closed MacFriis closed 2 years ago

MacFriis commented 2 years ago

Describe the bug

Trying to send background notification, to make my app update when changes in the backend, makes it imperative that the app is updated. it works perfectly when the payload has a alert, but without the alert and only '''hasContentAvailable''' the notification never reach the app.... not on sandbox at least

To Reproduce

create a payload that contains an alert

        let payload = APNSwiftPayload(alert:APNSwiftAlert(title:"You got new credit"),hasContentAvailable:true)
        let creditNotification = CreditUpdatedNotification(aps: payload)

and send it then remove the alert and try to send that one

        let payload = APNSwiftPayload(hasContentAvailable:true)
        let creditNotification = CreditUpdatedNotification(aps: payload)

and send it. I don't get anything on my devices in the second one, but the first is fine

Steps to reproduce the behavior:

  1. create an backend app
  2. add the aps package
  3. create an endpoint or another tricker to send the APN
  4. have an app that registers for APNs and receives the apn
    • implement the application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
  5. try debug when sending with hasContentAvailable with and without the alert:

    Expected behavior

I would expect the didReceiveremoteNotification to be called in both cases, as the hasContentAvailable is set to true. but it is only called when there is a alert with the payload.

Environment

using Ngrok as proxy pass when developing.

idelfonsog2 commented 2 years ago

Hi @MacFriis did you enable the background+remote notifications in the background modes?

which is different from the capability of push notification

MacFriis commented 2 years ago

Hi @idelfonsog2, yes I have had this on all along, and I have made a lot of Remote Notification on Apple devices using other libraries for C#, and finished services where I can get the "content-available" to work without having a message within the notification. I can't see what I'm doing wrong if it is working in the library.

0xTim commented 2 years ago

This is probably better suited to https://github.com/kylebrowning/APNSwift as this package just proxies directly to that and that package does the actual sending.

Any idea on why this may be happening @kylebrowning ?

kylebrowning commented 2 years ago

Yup. This should be handle upstream. I’ll take a look!

magnolialogic commented 2 years ago

+1, running into this while porting a service from Python/PyAPNs2 to vapor/apns

magnolialogic commented 2 years ago

@MacFriis FWIW using apns.send(rawBytes: ...) works for me, instead of apns.send(payload: ...) or apns.send(notification: ...)

FriisConsultApS commented 2 years ago

@magnolialogic I'll give it a try

marekpridal commented 2 years ago

@magnolialogic can you please send example code how you were able to send an update notification using rawBytes? I wasn't able to do so with code below.

Payload:
"{
    "aps" : { 
         "content-available" : 1 
    }
}"

request.apns.send(rawBytes: payload,
                                  pushType: APNSwiftConnection.PushType.alert,
                                  to: apnsToken,
                                  expiration: nil,
                                  priority: nil,
                                  collapseIdentifier: nil,
                                  topic: nil,
                                  logger: request.logger,
                                  apnsID: nil)

EDIT: Got this working by using APNSwiftConnection.PushType.background although testing of this feature on iOS is really tricky.

0xTim commented 2 years ago

I'm going to close this as it looks like there's a workaround and if you're having issues you should create an issue at https://github.com/kylebrowning/APNSwift

DanSessions commented 2 years ago

Can anyone share the code for the workaround? Can't seem to get it working.

FriisConsultApS commented 2 years ago

Sorry, I have abandon the servicer side swift all together... now back on dotnet 6

marekpridal commented 2 years ago

This is the workaround which work for me

request.apns.send(rawBytes: payload,
                                  pushType: APNSwiftConnection.PushType.background,
                                  to: apnsToken,
                                  expiration: nil,
                                  priority: nil,
                                  collapseIdentifier: nil,
                                  topic: nil,
                                  logger: request.logger,
                                  apnsID: nil)
idelfonsog2 commented 2 years ago

Thank you so much @marekpridal for sharing.

Mine was the followoing:

private func sendPushes(_ tokens: [String], alert: APNSwiftAlert , on req: Request) async throws {
...
      for token in tokens {
         do {
            try await req.apns.send(payload,
                                    pushType: .alert,
                                    to: token,
                                    with: JSONEncoder(),
                                    expiration: Date().addingTimeInterval(3600),
                                    priority: 10,
                                    collapseIdentifier: nil,
                                    topic: applicationTopic,
                                    logger: req.logger,
                                    apnsID: apnsID).get()
...
// to complete
kylebrowning commented 2 years ago
    let payload = APNSPayload(hasContentAvailable: true)
        let acme = AcmeNotification(acme1: "hey", acme2: 2, aps: payload)
        try! await req.apns.client.send(acme, pushType: .background, to: dt, priority: 5)

this worked for me.