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.
Related
I have found similar questions on Stack Overflow, but none of them have cleared the point.
I am using Firebase Cloud Messaging for sending push notifications in my app. I am storing the messages received in a local database. When my app is active or in the background, my app is able to receive the notifications (delegate methods called properly) but if the app is being forced quit or not in the memory then also the device is receiving the notifications and sat in notification center but the none of the delegate methods called when the app is being launched by an icon. If a user clicks on Message in the notification center, then the app gets launched, but only the message clicked on is being received and not all of them (in the case of multiple notices have been received).
According to Apple - The system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
But even if the user launched the app still not receive the notifications which were received and sat in the notification center.
Here are the points followed by the app:
My app has no VoIP functionality.
Content-available has been set to 1.
Has enabled to receive background remote notifications.
All notifications sent has been received and displayed in the notification center.
{
aps = {
alert = {
body = "Push Notification Test Message";
title = Push Notification;
};
badge = 1;
"content-available" = 1;
sound = default;
};
"gcm.message_id" = "0:1499340350307980%361a2e5b361a2e5b";
m = "Push Notification Test Message";
tag = m;
}
If the app is being forced quit or not in memory then your app will not receive silent notifications(i.e. Content-available set to 1).
Only push notifications are received in above conditions.
If user clicks on Message in notification center, then app gets launched and only that clicked the message will be received in delegate methods.You cannot access all the messages in the notification tray.
There is no way to get push notifications for the application if app is not running. This is restriction . You are only can get and clear local notifications. So the another way of resolving your problem is saving your notification on the backend when you send it. Then after launching app , you can get notifications list from the server , and match it with id . You can send any parameters that you want in notification playload.
Your app should not rely on the delivery of push notifications. Delivery of push notifications is not guaranteed, as you have found.
Even if your app isn't terminated you may not receive all notifications; For example if the device is in airplane mode and multiple notifications are sent, only the last one is delivered when the device comes back online.
Your app should check with the server for new messages when it is launched or when a notification is received in order to "catch up".
You can also consider including a message payload in your silent notifications. This will be displayed to the user if your app is terminated to prompt them to open your app.
You need to handle method for push notification when the application is open from a tap on any notification. As soon as you tap on notification application will awake and lunch it.
In didFinishLaunchingWithOptions, you need to put below condition:
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithDictionary:[launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]];
}
It also called below method when notification is tapped:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
}
I have a problem with push notifications in iOS, in a similar scenary to this and this and another one.
Also, this post resume all possible situations.
In my case:
app is NOT RUNNING
content-available:1
UIBackgroundModes contains 'remote-notifications' and 'fetch'
If the user force-quit the app and receives a push notification, then it could open app from alert or from icon.
When the user tap on the notification the app will be opened and the following method will be executed:
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Handle for notifications when app is closed
if (launchOptions) {
NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
if (apsInfo) {
// handle notification
}
}
No problem up to here, I have the payload to doing something with that info (for example to fetch new data from server).
But if the user open the app from the icon I don't have any way to handle the payload (Although didFinishLaunchingWithOptions is execute, I don't have the aps info, according to docs here).
So, the question is, there are any way to solve that?
For example, I made the test with WhatsApp, and they handle that situation, (probably they are using VOIP notifications instead of Remote Notifications)
Regards
You should never assume that state has remained consistent between the time the notification has been delivered and the time the user has launched the app. Nor, even, that it is the same device. I'll frequently get a "Hey! Do something!" notification on my phone and, if my iPad is handy, respond to it on my nice big iPad screen.
Instead, you should round trip to the server and grab the most up to date state for that user at the time of app launch or activation.
I am trying to create a PushNotification app and I am working with PubNub. I have gone through all of the necessary steps to:
Include PubNub libraries on my workspace
Create the proper provisioning profile for the App
Ensured PushNotification was in the profile
Create the proper SSL certificate for the app
Add the certificate to the keychain access
Create the proper .pem file
Uploaded the file to PubNub
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSDictionary *)launchOptions
{
// #2 Register client for push notifications
NSLog(#" Options set");
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
[PubNub setDelegate:self];
return YES;
}
After getting some initial compile errors, I was able run the app on my device. When I ran the app on my device, I did not receive the "...Would Like To Send Yo Push Notifications" message as I thought I should. I am able to use the PubNun console to send a message and I see the messages are received via the log, but I do not get any notification or banner. I placed an NSLog in the didFinishLaunchingWithOptions method and I see the display in the log.
After that, I deleted the app from the device, deleted the provisioning profile form the device, restated Xcode, and compile and an again with the same results. Not sure what to try next.
EDIT: The specific problem you're running into has to do with the fact that you are running the application through Xcode, and in a nutshell you can't test production push notifications this way, you'd have to use the sandbox push server and certs. If you want to test prod pushes you'll need to distribute the application signed with an Ad Hoc provisioning profile. I'm sure there are a million ways to do this, but actually my two favorites are using Testflight and Crashlytics' new Beta feature, that allows you to distribute ad hoc builds to devices basically using a single line of code, automatically once you archive a new build. I would recommend Crashlytics because it also automatically handles extremely useful analytics as well as crash reporting.
If you are referring to the initial push notifications permissions pop-up, that will only be displayed once or the lifetime of the application. The ONLY way I believe to get around this is to uninstall the up and leave it uninstalled for 3 days (I believe this is the limit).
I'm unfortunately not familiar with PubNub, but in your application are you registering for push notifications and receiving a device token?
Kevin,
If this is all what you try to do, to receive notifications using PubNub service, than it is not enough.
After you receive device push notification token, you need to pass it to PubNub client library, for example like this with default configuration:
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialise PubNub client.
// Warning, you should use pub/sub/secret keys for your account (at admin.pubnub.com) to
// which you uploaded your development push notification certificate (in .pem file).
[PubNub setupWithConfiguration:[PNConfiguration defaultConfiguration] andDelegate:self];
[PubNub connect];
UIRemoteNotificationType type = (UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound);
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:type];
return YES;
}
- (void) application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[PubNub enablePushNotificationsOnChannel:[PNChannel channelWithName:#"my-test-channe-for-push-notifications"]
withDevicePushToken:deviceToken];
}
// Observe for some PubNub delegate methods related to push notification observation (or use completion block enabled version of API):
- (void)pubnubClient:(PubNub *)client didEnablePushNotificationsOnChannels:(NSArray *)channels {
NSLog(#"PubNub client enabled push notifications on channels: %#", channels);
}
- (void)pubnubClient:(PubNub *)client pushNotificationEnableDidFailWithError:(PNError *)error {
NSLog(#"PubNub client failed push notification enable because of error: %#", error);
}
If you see that push notification enabling has been successful for you, then use http://pubnub.com/console with pub/sub/secret keys from your account at http://admin.pubnub.com to send message into the channel (in our case "aps" payload should be sent to the channel with "my-test-channe-for-push-notifications" name).
Update Question :
The requirement is; as soon as I receive silent notification, I want to run a web service and show the one liner in the notification bar. It has to work if the app is killed also. any workaround ?
I am trying following method below.
I am new to iOS and i struggled with silent push notification,googled a lot and got stuck.
Will iOS awake my app when i receive silent push notification when app is not launched(i.e when app is removed from app switcher).
my pay load is as
{
aps: {
content-available: 1,
sound: ""
}
}
.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
int CA=[[[userInfo valueForKey:#"aps"] valueForKey:#"content-available"] intValue];
if (CA==1) {
my action...
}
completionHandler(UIBackgroundFetchResultNewData);
}
this method is called and works fine when app is in foreground and background.cant awake my app when app is not in running state(i.e app is not launched or killed from app switcher)..
If the App has been removed from the App Switcher, iOS will not awake your app, since the user specifically asked for closing your app.
If the user open your app at least once, and do not remove it from App Switcher, iOS will awake your app
What we have done server-side to handle this is :
If the user's app doesn't connect in the minute after we sent the silent notification, (you can set it as you wish), we send another non-silent push notification to alert the user.
Since the App (is not closed by the user) should automatically fetch data, it should take under a minute.
But for that of course you need a more complex server code than simply sending silent push.
EDIT : (Getting a vote up on this question showed me that it was outdated)
This answer is no longer True... you can now with PushKit wake up your app to do some minor things (like downloading small chunks of data to update content) even if the App has been removed from App Switcher.
Please checkout this:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler:
Use this method to process incoming remote notifications for your app.
Unlike the application:didReceiveRemoteNotification: method, which is
called only when your app is running in the foreground, the system
calls this method when your app is running in the foreground or
background. In addition, if you enabled the remote notifications
background mode, the system launches your app (or wakes it from the
suspended state) and puts it in the background state when a remote
notification arrives. However, the system does not automatically
launch your app if the user has force-quit it. In that situation, the
user must relaunch your app or restart the device before the system
attempts to launch your app automatically again.
This clearly says that Using new Background Push feature you can Awake the App Only if Your app is suspended Not if it is terminated forcefully by User.
As far I have tested when the app is terminate by the user (swiping up from the app switcher) you won't have background execution time due to silent push flag (content-available) or background fetch.
Also this:
Also keep in mind that if you kill your app from the app switcher
(i.e. swiping up to kill the app) then the OS will never relaunch the
app regardless of push notification or background fetch. In this case
the user has to manually relaunch the app once and then from that
point forward the background activities will be invoked. -pmarcos (Apple worker)
From apple forums: https://devforums.apple.com/message/873265#873265
You CAN get a PUSH-notification and work with it. I know a little way to do this... Open the AppDelegate.m and and find or put this method - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions.
After that, put into this method code like mine:
NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (userInfo) {
NSDictionary *apsInfo = [userInfo objectForKey:#"aps"];
NSString *alertType = [apsInfo objectForKey:#"type"]; //my own param in PUSH-notification
globalPushType = alertType; //global variable for working with it in some ViewControllers after app's load
}
I know, this helps a lot of people. =)
I wrote a simple messaging system, which allows sending brief messages from web interface to devices, in form of push notification.
On android, everything went well, once device receives notification is sends delivery confirmation receipt back to server, then read acknowledgement. Obviously, delivery confirmation often happens while app is running in background or phone is asleep.
I wrote similar app for iOS. How surprised I was that application: didReceiveRemoteNotification is not called when app is not active!
Is it really impossible to track message delivery without user interaction when app is not active? Others have suggested keeping log of messages on server and sending them when app opens, but this still requires user interaction.
Is there a way around apple restriction on background services? Can I somehow make my app use sound or location service, to allow simple POST request while in background?
In iOS7 you can use push notifications with background fetch, which is a remote notification with the content-available flag set. Example payload: {aps: {content-available: 1}}.
In this case iOS will wake up your app (there are some limitations see: Will iOS launch my app into the background if it was force-quit by the user?).
After your app is woken up you have 30 seconds to send to your server the push notification receipt confirmation.
You'll also have to enable the "Background fetch" capability in the Target background modes and update the AppDelegate to include this method:
- (void)application: (UIApplication *)application didReceiveRemoteNotification:
(NSDictionary *)userInfo fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler
So this requires a bit of work from your side.
I hope this helps.
For iOS there isn't any direct way that provides any info regarding the actual delivery, but I found one workaround which I tried and it is working fine.
Use "Notification service extension", the main use of this is to provide rich notification, so it basically wakes our app whenever new push comes and gives around 30 seconds of time perform our task like download an image to show in the notification. We can use this app wake up feature to call our backend.
So send some unique id with payload and from this method call your backend server with the push id, by this way you can be sure that push notification is delivered into the device.
This will work all state of the application, even in the killed state, so this is full proof and we can rely on this workaround for delivery info.
Reference link: https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension
Mis-using background services is a good way to get your app rejected. Apple are pretty strict on what an app can do in the background.
As a user, if I found out that an app I'd installed was making web requests in the background with no good reason, it would be swiftly deleted!
Push notifications are a one-way message - there is no guarantee that a notification has even been delivered, never mind read. I suggest you read up on the APNS here.
When application is not in Active state application: didReceiveRemoteNotification method won't be called .
If you want track the notification information when application is not in active state follow the below procedure.
application didFinishLaunchingWithOptions: method will be called every time when we open the application
from this method we are getting NSDictionary object called launchOptions. From this launchOptions dictionary we will get the notification data in the form of dictionary for the key UIApplicationLaunchOptionsRemoteNotificationKey
find the code from below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *remoteNotify = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
//Accept push notification when app is not open
if (remoteNotify) // it is only true when you get the notification{
// use the remoteNotify dictionary for notification data}}
http://cydia.saurik.com/package/backgrounder
Check that out, for th source, click on Developers Page.
If its not apples way, there is no way.
That's where jailbreaking comes in. You might have to make your app jailbreak compatible and take advantage of a lot more power.
I'd say for what your looking for, make a new version of Backgrounder that works they way you need it.