I have an app currently in beta-testing that has messaging functionality. It's set up to deliver a push notification when a user receives a new message from another user. The only time push notifications work is when a user sends a message to me specifically. If I try to send a message to any other user or any users message each other that don't include me, push notifications do not work. Only messages sent to me trigger push notifications on my device.
Here are some simple screenshots from Parse showing one push that sent properly and one that did not.
This is a private message sent from another user named "Alissa" to me in which I receive the push notification properly (as you can see by "pushes sent" = 1):
Here are the details of said push:
Now, here is a private message sent from my device, the same device that received the push notification properly, back to "Alissa". As you can see, the "pushes sent" = 0, meaning my device sent the message but the recipient did not receive the push notification:
And here are the details of that push, containing virtually identical information to the working one sent to me:
Finally, here is another push not working sent between "Alissa" and another user that is not me, therefore 2 users separate from my device.
This is the pattern when I look at a list of all pushes from users in my app. They all have "pushes sent" = 0 except for when a push is sent to my device, "pushes sent = 1".
I've printed to the console in my push notification method completion handlers and they indicate that the push was sent successfully when I send a message to another user. I will also point out that my device is being used for development of this app.
Also as a side note, it did not always use to be like this. A couple weeks ago everything was working normally. I released multiple new builds and never had a problem.
Can anyone guide me in the right direction here?
Edit: Below I've included more details including code in my app and
details of my developer account and Parse backend.
Relevant code in my app
The following is code I have in my AppDelegate as recommended by Parse to include for setting up push notifications. It's worth noting that the println statements "did register user notification settings" and "did register for remote notifications with device token" are both logged properly on app launch.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// ...
let userNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge
let settings = UIUserNotificationSettings(forTypes: userNotificationTypes, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
// ...
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
println("did register user notification settings")
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
PFInstallation.currentInstallation().setDeviceTokenFromData(deviceToken)
PFInstallation.currentInstallation().saveInBackground()
println("did register for remote notifications with device token")
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
println("didFailToRegisterForRemoteNotificationsWithError: ", error.localizedDescription)
}
This is code I have included when a message is sent to another user. It's also worth nothing that the println statement "success" is logged properly.
PFInstallation.query().whereKey("user", equalTo: incomingUser)
PFPush().setQuery(pushQuery)
let senderName = PFUser.currentUser()!.objectForKey("name") as! String
let data = [
"alert" : "New message from \(senderName)",
"badge" : "Increment"
]
push.setData(data)
push.sendPushInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
if success {
println("success")
} else {
println(error?.localizedDescription)
}
}
Relevant details from my developer account
Here is a screenshot showing my App ID in my developer portal. It seems to show that push notifications are enabled properly (I deleted and re-added all certificates with a new provisioning profile)
Relevant details from my Parse account
Here are my push notifications settings within Parse. All this information was updated yesterday when I recreated certificates.
This might provide some level of insight although I'm not sure what. This is a screenshot of my PFInstallations table in Parse. An installation is created anytime someone logs in/opens the app. I just ran the application on my device and my record in the table is the top one. What's different from the rest is that there is a value in the "deviceToken" column only for my device. When I delete my PFInstallation record and restart the app to recreate it, there is always a value created under "deviceToken".
Relevant details from Xcode
Here is an expanded view of the code signing in my Xcode build settings. This code signing is identical in both the project and the target code signing.
Again, push notifications are working for all users messaging other users and only not working when a message is sent from my device to any other user.
Start with what makes your device unique, and it's status as a development environment device is the likely culprit.
A good place to check is your device's build and the consequent push certificate being used. If your device is in dev mode (meaning you are building and deploying to your phone via Xcode), then it will use the push certificate for Development instead of Production. (For more on this difference, see this great article by Ray Wenderlich)
The key factor here is that only your device will use this different certificate. If it's revoked/broken/not installed, only your device will have this problem.
You can also test this by deploying the app to your phone via TestFlight / HockeyApp / etc. instead of letting Xcode load it.
UPDATE:
Just pouring over the code, checking for errors. One thing already of note: your didFinishLaunchingWithOptions includes an extra PFInstallation.currentInstallation().saveInBackground() - you should remove that and only have it in the didRegisterForRemoteNotificationsWithDeviceToken method.
This is why only your device has an ID in it's PFInstallation, and is probably why your device can't reach anyone else - the push system is working, but it no no address to call out to from there; it would be a silent fail on the push, not on the parse system.
Have you tried having your users send a push to each other, or only to you and from you?
Related
My code is in Objective-C
Firebase side
App created
General settings --> done
APNs Auth Key --> done
Apple developer account side
App ID --> done
Dev and Distribution certificates --> done
Dev and Distribution profiles --> done
App side
My AppDelegate calls registerForRemoteNotifications without any error and the method "didReceiveRegistrationToken" is able to return a string like in the following: NSLog(#"Remote instance ID token: %#", result.token);
First item confirms that my app is able to reach Firebase Server and APNs because a TOKEN returns always!
I have implemented all functions didReceiveRemoteNotification both if I am receiving a notification message while the app is in the background and if it isn't.
GoogleService-Info.plist --> moved inside my project
PROBLEM
The problem is my app is not able to receive any notification I am going to send by using the firebase console. didReceiveRemoteNotification never called!
I have read all your feedback on other questions but I didn't solve my problem.
UPDATE #1
Thank you iDev750 for your answer!
My problem is I do not receive notifications on my app when I send them from the firebase console or directly from my backend. In my opinion if I do not receive a notification it is impossible that didReceiveRemoteNotification is called, are you agree with me?
Anyway, as you said, I sent a push message directly to my token/device and the result is in the following:
{"multicast_id":6185922XXX,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1543141675131005%YYYY"}]}
So, it is sure the message has been sent, otherwise the output should be something like The request's Authentication (Server-) Key contained an invalid or malformed FCM-Token (a.k.a. IID-Token).
I hope I was clear with this my second message. Do you have any idea to help me?
Thank you so much!
Here you said two points in your question.
Notification is not receiving in your app.
didReceiveRemoteNotification never called.
First, which is your problem? becasue both are different issue.
You can do one thing that just install your app in iPhone and paste your device token on Firebase console and send test notification on that device. Just forget about "didReceiveRemoteNotification" method that calling or not.
Now, if you are getting notifications but didReceiveRemoteNotification is not calling then check my answer:
https://stackoverflow.com/a/53460880/1673192
If notification is receiving on the device, might be some other issue like -
Is push notification enable for your AppId created on AppStore?
Is push notification enable in your app -> Targets -> Capabilities -> Push Notifications
Check these points and let me know still you have any issue.
edit: Updating question with new information.
So there's a number of questions out there about Firebase notifications not being received but I've not found one quite like this.
I've recently switched over from using the old p12 APNs certificates to the glorious new p8, and uploaded it to all of my projects on Firebase v4.0.0.
What I'm seeing is, when I do a fresh install of any of my projects, I can send & receive push notifications fine. But after some time, the token changes - and it just stops working - Firebase says "message sent successfully" but no message is received.
Weirdly - my app still receives push notifications to the previous Firebase token, while the new one reported by Firebase isn't working.
Following the advice at Debugging Firebase Cloud Messaging on iOS, I happily debugged the morning away:
Are there any error messages coming back from my Postman firebase attempts? Nope, success:1 every time
Am I getting pushes with app in the background, foreground or neither? Neither.
Are my AppDelegate remote notification registration attempts working successfully? Yes.
Can I directly send a message over APNs, using the new .p8 file? Yes (thanks to this). Messages are being received when I send them directly over APNs just fine!
In the Firebase console, if I send a message to all devices in a project, I receive the message to all devices. But if I try to limit it to my debug device via its FCM token, I get nothing.
So there's one last link that's just not working - appearing to work perfectly for new installs and then bombing after some amount of time - the FCM to APNs link. But how would I debug it?
Here in
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
...
NotificationCenter.default.addObserver(self,
selector: #selector(self.tokenRefreshNotification),
name: .firInstanceIDTokenRefresh,
object: nil)
return true
}
func tokenRefreshNotification(_ notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
// Here you get the refreshed token
// here you can connect to fcm and do subscribe to notifications
}
}
Hopefully it will solve the problem.
I'm trying to set up iOS Push Notifications and I've been going round in circles for the past 4 hours and got nowhere.
The app is written in Swift 2.3.
I set up the AppBoy application...
Appboy.startWithApiKey("blahblahblahblah", inApplication:application, withLaunchOptions:launchOptions)
And I can see that there are users of the iOS app in the segment I created.
In code I then register for notifications and use this code to send the device token up to AppBoy...
extension NSData {
func hexString() -> String {
// "Array" of all bytes:
let bytes = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes), count:self.length)
// Array of hex strings, one for each byte:
let hexBytes = bytes.map { String(format: "%02hhx", $0) }
// Concatenate all hex strings:
return hexBytes.joinWithSeparator("")
}
}
And this...
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let token = deviceToken.hexString()
Appboy.sharedInstance()?.registerPushToken(token)
}
However, when I update the filter on the Segment in AppBoy to filter by "Push Enabled" I get 0 devices. (I'm not even sure if Push Enabled is the correct filter?)
As a secondary question. The certificate that I upload to AppBoy is telling me it is a "Universal certificate" and the newest method of delivering notifications. Is this the right certificate to upload to AppBoy?
I have created a campaign with the segment I created and it shows as having one message delivered.
But whatever I do nothing is coming through to my device.
The version of the app installed on my device is the one downloaded and installed through Crashlytics.
Thanks
Update
OK, so now I'm getting devices showing up as "Push Enabled" but when I try to send a push notification the error log in the developer console shows "Error sending to a bad push token..."
The certificate I have shows like this...
Can anyone explain what I'm doing wrong? I have followed every troubleshooting guide and triple checked the setup and redone every step several times.
If you are getting the prompt to accept push notifications from your app but your user profile within Braze's dashboard is not being updated as expected, make sure that you are correctly formatting the device token before passing it back to Braze. Code below and more details available here.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = String(format: "%#", deviceToken as CVarArg)
Appboy.sharedInstance()?.registerPushToken(deviceTokenString)
}
If you are worried about which certificate to add to the Braze dashboard, I recommend using a .p8 downloaded from your apple developer account. Detailed instructions here.
An easy mistake to make is forgetting to update the environment setting in the Braze Dashboard and within your apps entitlement settings. While you are developing and testing the app on a simulator or side loaded onto your test device, be sure that the environment setting just above the certificate details in the Braze dashboard is set to Development. Once you move it to TestFlight and the App Store, you will need to update this to Production.
Hope this helps.
I'm working on a chat app and I need to know when a push notification is received to reload the conversation view with the new message. It's working well if the user allows the app to send push notifications to his device (with the notification dialog). However, if he taps "No" in this dialog, the following code, which registers the user device token to my database, is not executed :
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
// Update the OneSignal id for this current installation
oneSignal!.IdsAvailable({ (userId, pushToken) in
if (userId != nil) {
let installation = PFInstallation.currentInstallation()
installation.setDeviceTokenFromData(deviceToken)
installation.setValue(userId, forKey: "oneSignalId")
installation.saveInBackground()
}
})
}
Then, how to get the user device token, if he taps "No" in the notification dialog, so I can still target him to send silent push notifications ?
Thanks!
Actually it is possible to do it but not with OneSignal.
Apple push notification does support push on the background, That means even if user doesn't grant access to notification it would just not show on his screen when he gets one.
With OneSignal the issue is that the system doesn't send a push to users who have disabled push notifications. That means that your notification won't ever reach your app because it won't ever be sent through Apple Push Service.
I suggest you use another vendor for that (it works with Parse-Server by the way).
If you want to fetch the data in background instead of using push I suggest you use "Background fetch", That would wake your app from time to time and let you run a bit of code to check if there is anything new.
Sorry mate, you can't send apple push notifications to a device if the user doesn't allow Push Notification in settings, in that case you need to follow other methods to detect change in data.
You can implement sockets. i.e UDP connection which listens to the server for any incoming messages. You need to start the connection in the chat ViewController and and if you receive a packet indicating there is a chat message, you can reload data. Also there is live messaging service such as xmpp which is kind of the same but more improved with much more chat support. Chat services like Whatsapp uses them.
Another option is to reload data every 4 or 5 seconds using a NSTimer object. Call the api in background, so the user won't know it is constantly refreshing and update if there is new data. Also invalidate the timer once you go out of scope of the chat. The one i used, used the same technique with calling the api service both in chat view controller and conversation view controller.
I have made a sample PushTest app for Push Notification using this tutorial.
And using above tutorial I got the message that 'PushTest' would like to send you Push Notification (exactly once) and after that I delete the app from iPhone, restart the iPhone but unable to get the same message again.
I have run the script sample.php (updating the changes suggested) and got the message 'connected to APNS' & 'your message send'.
But I didn't receive any single push notification.
Please guide me where I am wrong?
Or what shod I try for push notification receive.
You will not receive Push only in 2 cases
1.) If your application is in foreground.
2.) you device token is not valid for receiving the push notification please check both the condition if you still do not receive push please let me know.
Thanks
BE AWARE OF THE BATTERY ISSUE, WHICH BLOCKS YOU FOR ONE DAY OR MORE
Never start testing pushes in development mode (tethered phone) unless the phone is FULLY CHARGED.
https://developer.apple.com/library/archive/technotes/tn2265/_index.html
If your notification payload contains the content-available key, your app will receive the notification if iOS or OS X determines it is energy-efficient to do so. If the energy or data budget for the device has been exceeded, your app will not receive any more notifications with the content-available key until the budget has been reset. This occurs once a day and cannot be changed by user or developer action.
In general, notifications (particularly when you are tethered) are incredibly flakey regarding battery state of the phone. (Also, some of the stuff mentioned in that article, which is very old, is plain wrong.) Basically you often JUST WILL NEVER GET notifications if your phones enter "don't get notifications because of battery" mode - and it can go on for days.
Notifications do (or did) prefer cellular WTF!!!
On iOS, push notifications use the cellular data network whenever possible, even if the device is currently using Wi-Fi for other network activity such as web browsing or email. However, the push service will fall back to Wi-Fi if cellular data service isn't available.
This has changed a lot with different iOS versions but it's a huge hassle.
>>>>> !!! CRITICAL TIP !!! <<<<<
Don't forget that:
Build to a tethered phone. You will only get the "sandbox, development" push notifications. BUT THOSE BARELY WORK - THEY ARRIVE VERY LATE, DO NOT WORK IN SOME REGIONS, AND SO ON. THEY ARE SO FLAKEY THEY ARE USUALLY NOT WORTH TRYING.
Increase build number, build normally for Test Flight, send to test flight, and then install from Test Flight. You will now get CORRECT, NORMAL APPLE PUSH NOTIFICATIONS.
Very confusingly you !!DO!! get REAL push notifications on development Test Flight builds.
That is to say - when you build to TestFlight you DO GET exactly the same "real" push notifications as for actual apps published on the app store and used by your public users - real, true, APNS push notifications.
The incredibly confusingly-named "development, sandbox" push notifications are ONLY for "tethered phone builds". (AND, to add confusion on confusion, the "development, sandbox" push notifications are very unreliable, so you never really know if they are working or not.)
Read more here! https://stackoverflow.com/a/60550859/294884
Make sure you are using push notification enabled provisioning profile. and then check if you are sending token to server.
I have followed the same tutorial.
Make sure your app is listed in notification center, and it's alert type is anything but not none.
You need to check your notification in 3 conditions,
When your app is open, in background, and when closed.
For that, you need to in check these methods
// To Register your device token
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
//If your app is not able to register
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{}
//Your app receives push notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
UIApplicationState state = [application applicationState];
// If your app is running
if (state == UIApplicationStateActive)
{
//You need to customize your alert by yourself for this situation. For ex,
NSString *cancelTitle = #"Close";
NSString *showTitle = #"Get Photos";
NSString *message = [[userInfo valueForKey:#"aps"] valueForKey:#"alert"];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#""
message:message
delegate:self
cancelButtonTitle:cancelTitle
otherButtonTitles:showTitle, nil];
[alertView show];
[alertView release];
}
// If your app was in in active state
else if (state == UIApplicationStateInactive)
{
}
}
Please check in your device's Settings if notifications for the application are on and ensure that the type of the notification is not 'None' in Notification Center.
Make sure, that you select right provision profile
and that your app is minimized. If app's not minimized use
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"info %#", userInfo);
}
Other useful information about issues.
For TESTING pushes you can use APN Tester Free.
Attention: insert token WITH spaces.
I was not getting anything in:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any])
But my compiler stopped on breakpoint in
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
I ran into a similar issue. Everything was done correctly in the code. I was running the app with a development profile and push notifications on the server (iOS) pointing to production. Make sure your provisioning profile matches the server setting(Sandbox vs. Production). You can also make sure your device is registering correctly.