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.
Related
So I am having an issue that I thought you guys might be able to help out with. I have an iOS app built by a third party vendor. I have an api that i built myself to work along side the app to consume data from the healthkit database on the device. The flow is this:
User downloads, installs and authorizes app to access healthkit data.
User opens app and logs in via the api.
App sends healthkit data back to api with user credentials so I can store data sent and attribute it to a user.
All works great. Now the part that isn't working so great. We're using FCM to send silent notifications with an attribute in the data object of
{ task: syncnow }
when this silent notification is received, it checks if the task is syncnow and if so, it sends the healthkit data to our servers so the users don't have to remember to manually sync it everyday. The problem is that it only seems to be received when the phone is awake and not locked. The app seems to wake fine if the phone is actively being used, but if the phone is locked and the screen is off, nothing comes through. I've tried adding a sound to the aps object on the JSON, I have
content_available: true
in the aps object as well. By all accounts, it should be working as intended, but it isn't. FCM always returns successful sends to all in the array of users in the to object as well.
my JSON structure looks like this:
{to: [array_of_fcm_tokens], data:{task: syncnow}, aps: {content_available: true, sound: ''}}
I've also tried moving the content_available to the top level of the object instead of in the aps object, I've tried different variations of content_available, content-available and different value types(string, int, bool). Nothing seems to work. What am I missing? Any help would be greatly appreciated!
Here's the possibilities to fix
1) Add "content-available" = 1 in your payload
2) Receive it via
func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable: Any],fetchCompletionHandler completionHandler:#escaping (UIBackgroundFetchResult) -> Void) {
}
3)Make sure your apps background refresh is on in device settings
4)Make sure you have added background mode for remote notifications in app
5)Restart the device
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.
We are currently in the process of preparing an update for an exisiting app, which provides push notifications via Firebase, which uses a token-based APNs connection.
Due to changes in the backend, we want to transition to OneSignal, which is certificate based.
Since the app is going to be released as an update, we want to maintain pushes via Firebase during a transition period, while updated versions should be able to receive pushes via OneSignal.
My question is: can I use both at the same time for one App-ID? Or are they going to interfere with each other?.
Apple's docs mention that
To send notifications, your provider server must establish either token-based or certificate-based trust with APNs using HTTP/2 and TLS.
but don't say anything about implementing both at the same time.
You actually can use both of them in parallel.
You also can generate 2 certificates and use them in parallel as well.
You also can use a single certificate/token from many places.
There are no any restrictions with this - certificate/token is only used to identify who you are, your App ID.
Since you've mentioned "receive pushes via OneSignal" I am assuming you are talking about iOS app, but I believe this is more of a backend problem. Because on iOS all you have to do is
register for push notifications via project settings
ask for permissions (Info.plist)
handle in appDelegate func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) and func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
setup correctly the developer portal for your project (certificates, permisions etc.)
All the push notifications that are coming to the device are coming from APNs, so your app cares neither about the Firebase or the OneSignal.
I believe your app will have OneSignal SDK in it, not the Firebase after the update.
So I think you need to handle the sending of push notifications via Firebase and OneSignal on the server during the transition period. Your server needs to communicate with both of those services at the same time. APNs will handle the rest of the delivery for you.
You can always use sandbox servers for a tryout before production.
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 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?