I'm using Plot Projects for iOS.
When I have finished filtering notifications through the PlotFilterNotifications method, I use filterNotifications.ShowNotifications to send these notifications to iOS.
The problem is, this doesn't seem to add them to the notification centre in the usual way, as when I check the UIApplication.SharedApplication.ScheduledLocalNotifications call, I get back an empty array. Also none of the usual methods work for removing this from the notification, such as UIApplication.SharedApplication.CancelAllLocalNotifications or setting the badge count to 0.
I have tried scheduling the notifications manually by taking the notification from the PlotFilterNotifications method and bypassing the filterNotifications.ShowNotifications method, and cancelling this notification when the user receives an exit notification for the site if the scheduled time has not yet passed, but if a user passes through a site too quickly the notification doesn't get cancelled so I do need to use the built in functionality.
You call the method filterNotifications.ShowNotifications with all passed notifications in the list, and then try to cancel/clear them straight after that? It is then possible that you try to cancel them before they are sent, since they aren't sent instantly when that method is called. That work is done on a different thread, since it involves some I/O operations.
You could alter the notifications passed to the notification filter to a single notification. Then only that single notification is sent. You change the message and other properties of the notification. A disadvantage would be though that the other notifications aren't considered sent in the statistics.
Related
I've been working with notifications for quite a while now, and I could've sworn that userNotificationCenter(_:didReceive:withCompletionHandler:) used to only be processed if the app was opened via the notification.
However, upon looking into actionable notifications, I found this:
When the user selects an action, the system launches your app in the background and notifies the shared UNUserNotificationCenter object, which notifies its delegate. Use your delegate object's userNotificationCenter(_:didReceive:withCompletionHandler:) method to identify the selected action and provide an appropriate response.
Does this mean that the seemingly universal didReceive delegate method now works even while the device is locked?
Or must the app always be opened to actually do anything meaningful in response to notification actions (writing to local database, sending HTTPS requests, etc.)?
Yes, the delegate works even if the device is locked. The app is only woken up if the user chose an action. Also, I am not sure how much time you will get before you invoke the completion block.
Important
If your response to action involves accessing files on disk,
consider a different approach. Users can respond to actions while the
device is locked, which would make files encrypted with the complete
option unavailable to your app. If that happens, you may need to save
changes temporarily and integrate them into your app's data structures
later.
From this Delegate Method : userNotificationCenter(_:didReceive:withCompletionHandler:) notification is works when your device is locked, but if you want to perform any action.
For Example: Suppose through Notification you want to pick any phone call within application then you have to setup another things as well.
you have to set up PushKit Framework within your application . As shown in images:
I have an iOS app integrated with Parse.com in which I want to schedule push notifications for certain dates/times. I am storing a push notification time on PFInstallation objects for users who have an upcoming event. I have a scheduled job running on Parse CloudCode that queries for push notification times that need to be sent within the next minute. Is this a good way to architect this? If so, how can I send this push? Parse.Push takes a query for it's where field, but queries only return up to 1000 results which doesn't scale at all for a free app. Thus, I'm trying to use Parse.query.each() which has an unlimited number of results. However, now I'm unsure how to send a push to each installation this way? Do I need to create another query within my each() statement? That seems redundant and inefficient.
(Note that the push notification is a silent notification with the content-available flag set so local notifications are not an option. Also the notifications can be cancelled by the user so scheduling the notification with the CloudCode push schedule API is not an option since those pushes can't be cancelled.)
You say, you store push notifications time on the respective PFInstallation object to circumvent the lack of support for canceling a push notification through Parse, great. We'll call that column ScheduledPushDate; That's the easy part; +1. The part you want to accomplish is actually scheduling a push notification using the given date. Great. Another easy part; +1. The hard part is doing it the way you want; -2. Parse.Push is not only limited by the where field. A lot of variables come into play when sending a push, for example, Parse doesn't even consider any objects that don't have a valid deviceToken so you can omit those objects immediately. The problem your running into is not the push itself, its not how to query for validation, its simply comes down to canceling it. Sure you can always change the date in ScheduledPushDate to be something in the year 2025 or simply negating it altogether, but that doesn't matter because you've already given the notification a scheduled date with the payload. Keeping it simple, and according to your target (you tagged iOS, so this is an answer specifically to client-side resources since you don't want to use local notifications or cloud code) you won't be able to cancel it, because within the guidelines given, you can only construct a push notification so many ways with Parse (client-side, cloud code, dashboard), and as of right now, only one of those options allows a successful means to cancel the process, and it's through the dashboard/console.
Lets say you do it the way you are thinking about:
Execute scheduled job to search for push times that need be fired within the coming minute. What is a "coming minute". Lets say a users time is 11:35.46 (11am35m46sec) and they want to cancel the scheduled notification and cancelled it at that moment, but your job fired at 11:35.00? Realistically, how often will that happen, not many, but it will happen and can happen. You should always code for every circumstance a user will encounter, not just the ones you want to prevent.
Additionally, you would be exhausting almost all of your API request limits if you do have a scaleable app as mentioned.
Lastly, to answer your question, no you don't have to do an innerQuery or additional query within the query.each function, as it's job is to iterate over each result of a query
I'm working with UILocalNotifications for the first time. Mostly working with repeating notifications. Most all makes sense, except one thing.
Apple Documentation states several cases for handling local notifications when they fire.
First, a case for when the user "taps the notification" when outside of the App:
If the notification is an alert and the user taps the action button
(or, if the device is locked, drags open the action slider), the
application is launched. In the
application:didFinishLaunchingWithOptions: method the application
delegate can obtain the UILocalNotification object from the passed-in
options dictionary by using the
UIApplicationLaunchOptionsLocalNotificationKey key. The delegate can
inspect the properties of the notification and, if the notification
includes custom data in its userInfo dictionary, it can access that
data and process it accordingly.
It also states a case for what happens when the user is inside the App:
If the application is foremost and visible when the system delivers
the notification, no alert is shown, no icon is badged, and no sound
is played. However, the application:didReceiveLocalNotification: is
called if the application delegate implements it. The
UILocalNotification instance is passed into this method, and the
delegate can check its properties or access any custom data from the
userInfo dictionary.
In both of those cases the developer can access the uilocalnotification and then decide what to do with it. However, in a third case - when the user, outside of the App, sees and ignores the notification and then later launches the App, no method is called that allows the application to know which notifications have previously fired?
At first I thought that this statement was describing that behavior, but now I am not sure:
On the other hand, if the local notification only badges the
application icon, and the user in response launches the application,
the application:didFinishLaunchingWithOptions: method is invoked, but
no UILocalNotification object is included in the options dictionary.
How can I handle the third case? How can I know which local notifications have fired? Do I need to iterate through my list and check all their times myself? Is there a better way to accomplish this?
You need to keep track of what is happening with your notifications. What I mean with this is that, because the notification has fired, and the user didn't launch the app because of a notification nor was your app running at the time of the notification, you need to check your sources to verify if a previously scheduled notification fired date has already passed.
The previous posting on here regarding deleting notifications from the notification center claim its not possible to delete individual notifications, only all of them.
However individual notifications do get deleted for the reminder app - set 3 reminders to fire in a couple of minutes, when they fire go to the notification center, now select one, after the reminder app launches go back to the notification center and that specific notification has been deleted but others remain. So how is this achieved?
The Reminders app probably fires local notifications. Local notifications can be withdrawn, using cancelLocalNotification: on UIApplication.
(Additionally, push notifications when sent using the enhanced call (first byte is 1) supports an expiry parameter (when sending, not inside the JSON payload) that is supposed to mean that this notification, if not delivered by a certain date, should not be delivered. It is possible that this parameter is also used in a similar way to hide received notifications.
It is also highly possible that Apple's own apps do whatever the hell they want.)
When the user taps on the notification:
If the app was running in the background, you retrieve it using AppDelegate's method didReceiveLocalNotification.
If it wasn't running, then the notification can be obtained with the didFinishLaunchingWithOptions method. You just need to search the launchOptions dictionary for the UIApplicationLaunchOptionsLocalNotificationKey.
If you want to delete specific notifications which have already fired, specially when the user doesn't enter the app by tapping on the notification, then it's probably better to store them in NSUserDefaults so that you can still obtain them later. That approach is explained here.
I have a iOS 5.1 application that registers to the APNS service to receive notifications. The register is successful and I receive the notifications correctly. The problem comes when I try to handle the notifications.
Once the application is running, the method didReceiveRemoteNotification in the AppDelegate is called correctly and so the notification is handled as intended. This, however, only happens when the application is running on the foreground.
However, when the application is running on the background or is simply stopped, that method is not called. I've read that you should add some lines to the method didFinishLaunchingWithOptions method to obtain the notification from the userInfo dictionary, and handle it. This works just fine, but ONLY when the application is opened by clicking on the notification at the Notification Center. This means that if you open the application by clicking on its badge, or simply by changing context if you were running it on the background, the app never realises that a notification came in. Additionally, if more than one notification was received, we can only handle one of them at once by clicking on the Notification Center, which is a pain :-)
Is there any way to read the pending notifications in the Notification Center? I know there is a way to flush them using the method cancelAllLocalNotifications but I haven't found a way to just read them. And I really need to handle all of them. I thought of implementing a communication protocol with the third-party notification server to retrieve the information again when the application comes to the foreground, but since the information is already in the operating system I would find it strange if it's impossible to access it somehow.
So, does anybody know a way to do it? Thanks in advance.
When a push notification arrives and the user clicks 'cancel', your app has no way to read that push notification again. You have to implement a separate functionality (most probably on server-side) to fetch a list of notifications sent to this device.
For example, if a chat functionality is provided in your app and you send chat messages via push notifications then you should also keep chat messages on the server. If a user clicks 'Cancel' on any push notification then that chat message will not be displayed on the iOS device. In that case when a app comes in foreground later, you make a call to the server and fetch all the past chat messages (sent via push notification).
Ok, So a possible solution would be to have another database table with the messages in with a 'read' flag and a messageID field? Which by default the read flag is NO, then when the app successfully reads this and displays, it updates the flag to YES?
And with only 256 bytes to play with, what sort of ID field length would be necessary?
Edit,
Executed this plan and its working successfully.