For some reason I am not receiving push notifications on my app anymore (though users are still).
I used to receive them in production and on test flight builds, but not builds directly from Xcode. But now I am not receiving them on production nor test flight and I do not know the issue.
I created new certificates for push notifications in the developer portal and have this code in the AppDelegate. Is there any reason that push notifications would just stop working? I have notifications enabled and have tried deleting + redownloading from the App Store, but no luck
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]) { granted, _ in
guard granted else { return }
// Enable or disable features based on authorization
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
Related
I have push notifications as part of my provisioning profile.
I have remote notifications and push notifications selected as my capabilities for all build types.
Is there anything else I need to do? When I build my app now I don't even see notifications available in the app settings. It's just gone completely.
I'm using react native btw.. dont think it matters but just throwing that in there. I feel like I'm missing one of those deep buried settings.
I've tried deleting and reinstalling app. restarting phone. cleaning project. removing and re-adding the capabilities. What's going on here?
There are two types of remote notifications: background update notifications(those whose payload contains a content-available: 1) and regular push notification. The former type is always silent and the user will see nothing, and the latter is where the user received a message on the lock screen.
For an iOS app, the background update notification is ALWAYS allowed without the user having to grant you any permissions. Only when you want to deliver notifications where the user will be alerted, will the user have to grant you the permission first. Therefore, when you enable the capabilities, you are telling the system that your app should be receiving notifications, but the system does not know which type, so it allows you to register to APNS and receive notifications in the background. Only doing this much means your user will see no alert prompting them to allow your app to send notifications and there will be no notification settings for your app -- the user can't turn off something they don't even know about.
In order to prompt your user to grant you permission, see the permission settings in the Settings app, and be able to deliver notifications with sounds and messages, you must, at some point in your code, ask the system for such permissions using the following code:
iOS 9:
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil))
then implement func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) in your App Delegate yo check if the user has granted you the permission. (Check if notificationSettings.types is empty. If it is, the user has denied it).
iOS 10 & beyond:
import UserNotifications
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted in
if (granted) {
// ...
}
}
When you execute these code, the system will immediately present an alert to the user asking them to give or deny your app the permission to present notifications that can contain an alert, a sound, and display a badge on your app icon. After making a selection, the user can go into the Settings app and review/change their selection, where you will now see your app has a notifications setting.
P.S. As the user can later revise and change their notifications settings to your app, you should never store the granted status in your app. Rather, use the proper APIs the get the current status each time you need it. For iOS 9, check is UIApplication.shared.currentUserNotificationSettings?.types is empty(empty meaning you have no permission), and on iOS 10 & above use UNUserNotificationCenter.current().getNotificationSettings { settings in ... } to check if the settings contain any types at all. Optionally, calling requestAuthorization could also directly return you the granted boolean value, and if the user has been alerted and made a choice, the requestAuthorization method will directly give you the user's choice without asking them again.
TL;DR You haven't asked the user for permissions yet. They will not see the permission alert, and you will not find a notification settings for your app in the Settings app until you've done so.
My coworker and I are building an app and implementing push notification feature utilizing AWS SNS API.
The issue here is that some devices work fine but some like iPhone 6,7,8 receive no notification regardless of the OS version (they're mostly iOS 11,12).
We've covered the basic by checking the below points:
notification turned on on all test devices
testers grant permission to receive notification at the app launch time
the p12 certificate uploaded to AWS is valid and the format is correct
The error messages we got from AWS CloudWatch Logs mostly were "bad device token" or "unregistered", but we are sure that we upload the device token as soon as we got it from APNS.
EDIT: actual code added
Register for notification (within didFinishLaunchingWithOptions)
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if let error = error {
print("\(error.localizedDescription)")
} else {
application.registerForRemoteNotifications()
}
}
Get token
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("Successfully registered for notifications!")
// upload token to our database for later use
}
Is there anything we are missing?
I want to send silent notifications to my tvOS application. Does this require asking the user for notification permissions? Or is it enough to just register for remote notifications and enable the matching app capabilities in Info.plist?
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted: Bool, error: Error?) in
if error != nil {
print(error?.localizedDescription ?? "error requesting notification authorization")
}
}
UIApplication.shared.registerForRemoteNotifications()
From Apple Docs
If your app's local or remote notifications involve user interactions, you must request authorization for the system to perfom those interactions on your app's behalf. Interactions include displaying an alert, playing a sound, or badging the app's icon.
In iOS, the fact of showing a notification and allow sending push content from the cloud to the app are two separate things. In your case the "silent notification" does not involve any interaction with the user, thus, you do not need to request this permission. But this does not prevent you from receiving the push token in order to push content to the app from the cloud. (you will receive a push token no matter what the user answer is).
I've never done this in tvOS, however as per the documentation it should be the same.
Do I need to register for remote notifications even when asking the
user is not required?
In the Apple's Local and Remote Push Notification Documentation, specifically in its Configuring a Silent Notification section, you would see that you will be needing to setup your project's capabilities, and specifically checking the Remote Notifications capability, like so:
Therefore you will need to setup the certificates and other necessary stuff in Apple's Developer Website. Hope it helps!
This is the same step required for silent and push notifications.
In iOS, tvOS, and watchOS, apps must have authorization to display alerts, play sounds, or badge the app’s icon in response to incoming notifications. Requesting authorization puts control of those interactions in the hands of the user, who can grant or deny your request. The user can also change the authorization settings for your app later in the system settings.
Source: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SupportingNotificationsinYourApp.html#//apple_ref/doc/uid/TP40008194-CH4-SW1
{
"aps" :
{
"alert" :
{
"loc-key" : "GAME_PLAY_REQUEST_FORMAT",
"loc-args" : [ "Jenna", "Frank"]},
"sound" : "chime.aiff"
},
"acme" : "foo"
}
Remove "sound":"chime.aiff"
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?
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.