urbanairship / ios-library

Urban Airship iOS SDK
http://urbanairship.com
Apache License 2.0
478 stars 265 forks source link

In-App messages / silent notification doesn't work #300

Closed ota-motomi closed 3 years ago

ota-motomi commented 3 years ago

Preliminary Info

What Airship dependencies are you using?

Version 16.0.0, also tried on 15.0.1

AirshipCore
AirshipNotificationServiceExtension
AirshipAutomation

What are the versions of any relevant development tools you are using?

Xcode 13.0, using SPM.

Tested on: iPhone6+, iOS 14.5.1 iPhoneXR iOS 14.4.2

Report

What unexpected behavior are you seeing?

Notification without alert are not received by the app, i.e none of the PushNotificationDelegate or InAppMessagingDelegate methods are called. In addition, no log appear in the console to indicate an error or that anything was received.

What is the expected behavior?

In version 14 notification without alert known as silent notification or in-app messages, called UAPushNotificationDelegate methods receivedForegroundNotification or receivedBackgroundNotification.

In versions 15/16 no method is called, also tried implementing InAppMessagingDelegate methods following the documentation but those methods are not called either.

What are the steps to reproduce the unexpected behavior?

Confirm this in-app message works in 14.8.0 but on16.0.0, it doesn't work :

{ 
   "audience": {
       "named_user": <user-id>
   },
   "device_types":[ 
      "ios"
   ],
   "notification":{ 
       "ios":{ 
         "content-available": true
      }
   }
}

With the alert it work on 16.0.0

{ 
   "audience": {
       "named_user": <user-id>
   },
   "device_types":[ 
      "ios"
   ],
   "notification":{ 
      "alert": "Hello world",
       "ios":{ 
         "content-available": true
      }
   }
}

Do you have logging for the issue?

This is the log that appear in 14.8.0 when sending the silent push above, nothing appears on 16.0.0

+[UAAppIntegration handleIncomingNotification:foregroundPresentation:completionHandler:] [Line 191] Received notification: {
    "_" = "6b8d8535-7f61-48fb-890a-6f154d59731e";
    aps =     {
        "content-available" = 1;
    };
}
rlepinski commented 3 years ago

@ota-motomi Could you share your notification delegate? Also are you doing manual or automatic integration ?

ota-motomi commented 3 years ago

@rlepinski Here is our notification handler we only support deep links no other fancy business, I'm not sure what's the difference between manual or automatic integration, but maybe this code will give you some insight:

import Foundation
import AirshipCore
import Keys

class UrbanAirshipPushNotificationService: NSObject, PushNotificationService {

    private weak var delegate: RemoteNotificationDelegate?

    override init() {
        let config = UAConfig.default()
        config.suppressAllowListError = true
#if BETA
        config.isInProduction = true
        config.productionAppKey = AppKeys().urbanAirshipAppKeyBeta
        config.productionAppSecret = AppKeys().urbanAirshipAppSecretBeta
#elseif RELEASE
        config.isInProduction = true
        config.productionAppKey = AppKeys().urbanAirshipAppKeyProduction
        config.productionAppSecret = AppKeys().urbanAirshipAppSecretProduction
#else
        config.isInProduction = false
        config.developmentAppKey = AppKeys().urbanAirshipAppKeyDevelopment
        config.developmentAppSecret = AppKeys().urbanAirshipAppSecretDevelopment
#endif
        UAirship.takeOff(config)
        UAirship.push()?.isAutobadgeEnabled = true
        super.init()

        UAirship.push()?.registrationDelegate = self
        UAirship.push()?.pushNotificationDelegate = self
    }

    func setDelegate(_ delegate: RemoteNotificationDelegate?) {
        self.delegate = delegate
    }

    func authorizationStatus() -> UNAuthorizationStatus {
        return UAirship.push().authorizationStatus.asUNAuthorizationStatus()
    }

    func registerForNotifications() {
        UAirship.push()?.userPushNotificationsEnabled = true
        UAirship.push()?.pushNotificationDelegate = self
    }

    func registerForChannel(_ channel: String) {
        UAirship.channel()?.addTag(channel)
        UAirship.push()?.updateRegistration()
    }

    func unregisterFromChannel(_ channel: String) {
        UAirship.channel()?.removeTag(channel)
        UAirship.push()?.updateRegistration()
    }

    func registerUniqueIdentifier(_ id: String) {
        UAirship.namedUser()?.identifier = id
        UAirship.push()?.updateRegistration()
    }

    func unregisterUniqueIdentifier() {
        UAirship.namedUser()?.identifier = nil
        UAirship.push()?.updateRegistration()
    }

    func clearBadges() {
        UAirship.push()?.resetBadge()
    }
}

extension UrbanAirshipPushNotificationService: UAPushNotificationDelegate {
    func receivedForegroundNotification(_ notificationContent: UANotificationContent,
                                        completionHandler: @escaping () -> Void) {
        handleNotification(notificationContent)
        completionHandler()

        clearBadges()
    }

    func receivedBackgroundNotification(_ notificationContent: UANotificationContent,
                                        completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        handleNotification(notificationContent)
        completionHandler(.noData)
    }

    func receivedNotificationResponse(_ notificationResponse: UANotificationResponse,
                                      completionHandler: @escaping () -> Void) {
        // Check the app was launch via notification (prevent from handling deeplink on foreground notification)
        guard notificationResponse.actionIdentifier == UANotificationDefaultActionIdentifier  else {
            return
        }
        if let deeplink = notificationResponse.notificationContent.notificationInfo[UADeepLinkActionDefaultRegistryAlias] as? String,
            let url = URL(string: deeplink) {
            delegate?.openLinkReceived(url: url)
        }
        completionHandler()
    }
}

We initialize this class on : func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool

rlepinski commented 3 years ago

That looks like the SDK 14.x one, could you share your SDK 16 version?

ota-motomi commented 3 years ago

@rlepinski Below is SDK 16 version, I tried version 16.0.2 as well but with same results.

import Foundation
import AirshipCore
import Keys

class UrbanAirshipPushNotificationService: NSObject, PushNotificationService {

    private weak var delegate: RemoteNotificationDelegate?

    init(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        let config = Config.default()
#if BETA
        config.inProduction = true
        config.productionAppKey = AppKeys().urbanAirshipAppKeyBeta
        config.productionAppSecret = AppKeys().urbanAirshipAppSecretBeta
#elseif RELEASE
        config.inProduction = true
        config.productionAppKey = AppKeys().urbanAirshipAppKeyProduction
        config.productionAppSecret = AppKeys().urbanAirshipAppSecretProduction
#else
        config.inProduction = false
        config.developmentAppKey = AppKeys().urbanAirshipAppKeyDevelopment
        config.developmentAppSecret = AppKeys().urbanAirshipAppSecretDevelopment
#endif
        Airship.takeOff(config, launchOptions: launchOptions)
        Airship.push.autobadgeEnabled = true
        super.init()
        Airship.push.registrationDelegate = self
        Airship.push.pushNotificationDelegate = self
    }

    func setDelegate(_ delegate: RemoteNotificationDelegate?) {
        self.delegate = delegate
    }

    func authorizationStatus() -> UNAuthorizationStatus {
        return Airship.push.authorizationStatus.asUNAuthorizationStatus()
    }

    func registerForNotifications() {
        Airship.push.userPushNotificationsEnabled = true
        Airship.push.pushNotificationDelegate = self
    }

    func registerForChannel(_ channel: String) {
        Airship.channel.editTags { editor in
            editor.add(channel)
        }
    }

    func unregisterFromChannel(_ channel: String) {
        Airship.channel.editTags { editor in
            editor.remove(channel)
        }
    }

    func registerUniqueIdentifier(_ id: String) {
        Airship.contact.identify(id)
    }

    func unregisterUniqueIdentifier() {
        Airship.contact.reset()
    }

    func clearBadges() {
        Airship.push.resetBadge()
    }
}

extension UrbanAirshipPushNotificationService: PushNotificationDelegate {
    func receivedForegroundNotification(_ userInfo: [AnyHashable: Any],
                                        completionHandler: @escaping () -> Void) {
        handleNotification(userInfo)
        completionHandler()
        clearBadges()
    }

    func receivedBackgroundNotification(_ userInfo: [AnyHashable: Any],
                                        completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        handleNotification(userInfo)
        completionHandler(.noData)
    }

    func receivedNotificationResponse(_ notificationResponse: UNNotificationResponse,
                                      completionHandler: @escaping () -> Void) {
        print("received noification \(notificationResponse)")
        completionHandler()
    }
}
rlepinski commented 3 years ago

Looks like the default value for backgroundPushEnabled changed from true to false in 15/16. You can fix it with: Airship.push.backgroundPushNotificationsEnabled = true ill have a patch next week with the fix as well.

ota-motomi commented 3 years ago

@rlepinski Thank you for looking into this, Airship.push.backgroundPushNotificationsEnabled = true fixed the issue.