IOS doesn't receive first notification in background - ios

IOS 13.7 IPhone Xr, Xcode Version 11.7 (11E801a)
I edited app scheme and set launch mode to "Wait for the executable to be launched". I run app, and send a simple notification on my device.
this notification:
{
"aps":{
"content-available":1
}
}
in xcode status changed from "Waiting to attach to test on iPhone" to "Running test on iPhone", but the notification wasn't received.
i try catch notification in this method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
Next notification I receive successfully. This case can be repeated after application reload.
Can you help me find out why I don't receive the first notification

Please try this payload :
{"aps":{"alert":"","content-available":1}}

If your app wasn’t running, the push notification is passed to your AppDelegate in the launchOptions
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
...
let notificationOption = launchOptions?[.remoteNotification]
if let notification = notificationOption as? [String:AnyObject]{
// received notification
}
...
}

Related

Silent push notification (APNS) can not received

I have set up the silent push notification for my app:
1. I configured the push notification from all places, i.e., XCode, Apple Developer portal with proper certificate
2. I enabled background capability
3. I included "content-available" in the json payload.
However, my App can not receive silent push sometimes.
To be more specific, neither
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
......
}
nor
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (_: UIBackgroundFetchResult) -> Void) {
......
}
has been invoked when the push message arrives.
How can I get the information in the push notification in such state?
I'm waiting online.
You question is twofold:
1. why the two delegate callbacks can not be invoked
2. what should you do to receive the data.
I did some hand test and here is the result:
1, when an app is in killed state, the two callback can not be invoked indeed
2. however, when you open the app next time,
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
......
}
can be invoked and you can get the data from there.
I hope this is useful.

Receiving Push Notifications on Swift with AWS Mobile Hub

I am currently developing and iOS app using Swift, which I am new to, and the code generated from AWS Mobile Hub, with AWS SNS to register devices and send notifications.
On my class AWSMobileClient I have the following code:
func didFinishLaunching(_ application: UIApplication, withOptions launchOptions: [AnyHashable: Any]?) -> Bool {
print("didFinishLaunching:")
// Register the sign in provider instances with their unique identifier
AWSSignInProviderFactory.sharedInstance().register(signInProvider: AWSFacebookSignInProvider.sharedInstance(), forKey: AWSFacebookSignInProviderKey)
var didFinishLaunching: Bool = AWSIdentityManager.default().interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
didFinishLaunching = didFinishLaunching && AWSPushManager(forKey: ServiceKey).interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
if (!isInitialized) {
AWSIdentityManager.default().resumeSession(completionHandler: { (result: Any?, error: Error?) in
print("Result: \(result) \n Error:\(error)")
}) // If you get an EXC_BAD_ACCESS here in iOS Simulator, then do Simulator -> "Reset Content and Settings..."
// This will clear bad auth tokens stored by other apps with the same bundle ID.
isInitialized = true
}
return didFinishLaunching
}
Which is called normally.
On my AppDelegate, I have the following:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
AWSMobileClient.sharedInstance.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
NotificationCenter.default.post(name: Notification.Name(rawValue: AWSMobileClient.remoteNotificationKey), object: deviceToken)
print("###--- DID REGISTER FOR REMOTE NOTIFICATION ---###")
}
Which is also called.
However, when I try sending a notification using AWS SNS, my function:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("###--- DID RECEIVE REMOTE NOTIFICATION ---###")
AWSMobileClient.sharedInstance.application(application, didReceiveRemoteNotification: userInfo , fetchCompletionHandler: completionHandler)
// This is where you intercept push notifications.
if (application.applicationState == .active) {
UIAlertView.init(title: "Notification Received", message: userInfo.description, delegate: nil, cancelButtonTitle: "OK").show()
}
}
Is never called.
Looking for a solution I read that since iOS 10 there are some chances that need to be made to deal with push notification, but I'm not sure about the correct ways.
How should I implement the code to receive the notifications?

Make a web request after receiving a push notification

I have a Swift 2 iOS8+ app where I need to make a request to fetch JSON data when my app receives a push notification.
When the user clicks on the notification the app will go and fetch the data but I really need the data to be fetched as soon as the notification is received. This looks to be possible, is this the case?
I've implemented:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)){
and checking the launch options in:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
I've also enabled:
background fetch
remote notifications
None of this seems to help. If this is possible I'd be grateful for any pointers/tutorials on this.
As of iOS 9, instead of a normal push, you can use silent push notifications. When your app receives a silent push, the user is not notified, but your app can perform actions based on this notification. Then, when your background actions is finished, you create a local notification for the user.
Check out this tutorial for info on how to use silent notifications:
https://www.raywenderlich.com/123862/push-notifications-tutorial

didReceiveRemoteNotification not called Swift

For some reason my didReceiveRemoteNotification is never called. I have done the following:
checklist of APNS:
Create AppId allowed with Push Notification
Create SSL certificate with valid certificate and app id
Create Provisioning profile with same certificate and make sure to add device
With Code:
Register app for push notification
Handle didRegisterForRemoteNotificationsWithDeviceToken method
Set targets> Capability> background modes> Remote Notification
Handle didReceiveRemoteNotification
Yet my function does not seem to get called. My code looks like this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if (application.respondsToSelector("isRegisteredForRemoteNotifications"))
{
// iOS 8 Notifications
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: (.Badge | .Sound | .Alert), categories: nil));
application.registerForRemoteNotifications()
}
else
{
// iOS < 8 Notifications
application.registerForRemoteNotificationTypes(.Badge | .Sound | .Alert)
}
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = ""
for var i = 0; i < deviceToken.length; i++ {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
apnsID = tokenString
println("******apnsID is \(apnsID)")
dToken = deviceToken
println("******dToken is \(dToken)")
NSUserDefaults.standardUserDefaults().setObject(deviceToken, forKey: "deviceToken")
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
println("***********didFailToRegisterForRemoteNotificationsWithError")
println(error)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
println("Getting notification")
var message: NSString = ""
var alert: AnyObject? = userInfo["aps"]
println(userInfo["aps"])
if((alert) != nil){
var alert = UIAlertView()
alert.title = "Title"
alert.message = "Message"
alert.addButtonWithTitle("OK")
alert.show()
}
}
add content_available:true in your request . for iOS payload data.You will get notification in didReceiveRemoteNotification. Now handle it.
As I found out having the same problem myself, in order for didReceiveRemoteNotificationto be called, the incoming notification music carry an "available_content" : true parameter with the notification payload. So in case of you sending the notification in a dictionary form , as was my case in device to device pushes, you just have to add it in the dictionary as you would specify other parameters as you would for sound or badge, also needed if you're using some sort of push service as Postman
Three steps:
Add logic here to handle incoming notification:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// Add your logic here
completionHandler(.newData)
}
Add Background mode to capabilities in target, and ensure to check 'Remote notifications'
While sending a push notification, add "content_available" : true
This worked for me in iOS 14/Xcode 12.3.

Catch push notification text on lock screen

How can I get the push notification text when the app does not run or in lock screen?
I did try:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
println(userInfo)
// or just
println("something")
}
But it doesn't print me anything. Is it wrong function???
didReceiveRemoteNotification function only called this condition.
while app will running and app in foreground.(alert not showing)
if app in background and click notification on home screen
if app not run in device didReceiveRemoteNotification function not called,
in this case user click notification in home screen, we identify app launched by notification or not in didFinishLaunchingWithOptions
UILocalNotification *localNotif =[launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
you get userinfo data in localNotif.userinfo
Try in Swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var userinfo : NSDictionary =launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
print(launchOptions);
return true
}

Resources