How to rise Reminder through PeriodicTask in WP7 Mango? - windows-phone-7.1

I'm developing wp7 Mango application. I run PeriodicTask and want to notify user according to some conditions. I'm using ShellToast for notification. But to my mind its isn't enough for my purpose. First of all ShellToast disappears after some time and user can easy miss this notification. Secondary that doesn't work when application runs. And minor issue - notification's sound is very quiet.
Reminder is more suitable for me. It is loud and doesn't disappear till user close it. But it isn't possible to create Reminder from background thread, so I've created Reminder on foreground side and set BeginTime = DateTime.MaxValue. On the background I just use ScheduledActionService.Find("ReminderName") for extracting Reminder and change BeginTime property to DateTime.Now. Unfortunately without success.
Does anybody has idea how to rise Reminder through PeriodicTask?

As you've discovered, it's not permitted to set a reminder from a BackgroundTask.
I think you would benefit by considering things from the users persective. As a user:
- would you an app that kept raising notifications that you had to respond to?
- would you want an app ignored the conventions of the platform
- would you want an app that always made loud noises? even if you turned the volume down?
If it's really vital to your app that you notify the user in a more prominent way you coudl send an SMS via an external service.
Or you could have the user subscribe to a web based calendar and then add your events to that calendar from the background thread. But when you get to this point it probably makes sense to move more functionality out of the background task and put that on the server too.

Related

Continue running code in background for Sending Notification to a Single User

I need to notify user when a certain condition is met but that condition might or might not meet in months. I need to run condition check in background (even when app terminates) so that I could detect condition is met (even if it happens after 3 months). If condition is met then I need to send notification only to a single user (not all users).
I am not sure what is the best way of doing it. Local Notification or Push Notification? I can not schedule a local notification in advance because I don’t know when it will meet the condition. I think Push notification is not needed because I am sending only one notification to only one user in several days/months.
I also need to constantly run this check in background. I know it can be run infinitely in background by using location update (significant monitoring or background navigation). But my condition checking code doesn’t actually require location updates. As far as I understand, Apple allows only location update or network related task in background (for few minutes). That's why I am thinking of putting my code in background location update code.
In my opinion , I should use local notification and put my code in background location update code so that I could check constantly if certain condition is met. This background check will schedule local notification and show it to the user who is using that device. I don’t think it is possible to schedule a push notification by code running in background.
In summary, I have following 3 questions
Should I put my code in background location update? If not, what is the right approach of running my code infinitely in background without location update?
Will Apple reject application if I put my code in background location update while location update code doesn’t actually send/receive current location?
What kind of notification should I use in this kind of situation where I send notification to a single user after months? Would you use Local Notification? or Push Notification.
Please reply. Any help is truly appreciated.
Thanks in advance.
This is a bit of a tricky problem unfortunately.
Apple won't allow you to create long-running operations in the background. As you mentioned, you can add code in the background with location updates or audio, but neither of those are very good solutions since (1) Apple will likely reject you from the app store and (2) the user will probably close the app if they notice a big locations banner at the top of their phone (or a weird background audio signal), and closing the app will kill your operation. For any truly long-running tasks it's probably best to set up a server and run a cron job or equivalent long-running operation. It's the only way you can know that the task will continue running.
Sorry, I was just answering one at a time, but as I mentioned above, yes, they'll probably reject your code for that. As a rule of thumb: if you think the Apple-created code you're using wasn't meant for what you're using it for, Apple will probably reject your app.
It sounds like you should use a remote notification. If you do use a remote notification, you'll probably want some sort of backend anyway. You could use a local notification to notify a user after a few months, but you would need to know the exact time to send it up front, which it doesn't sound like you would.
In summary: Try to build a simple BE. Maybe use Firebase Functions or something, and also build an APNS system to send pushes. In the app, tell the server to start processing the information and send the push back when it's done. The situation sounds like a perfect use case for server-side logic.
Hope that helps!

Schedule UILocalNotification based on changes to Core Data

I'm making a simple app with a Today Widget extension that logs events.
The user can tap a button in the app or the related Today Widget to log an event. These events are saved with Core Data any time the button is pressed either place.
Whenever a new event is logged in the app, I run a function called updateLocalNotificationsFromCoreData(). It handles the setup of UILocalNotifications based on the most recent event in Core Data after clearing the appropriate existing notifications.
However, when a new event is logged from the Today Widget, I can't use this function because I need to register the Local Notification with UIApplication.sharedApplication().scheduleLocalNotification(), and UIApplication is not available in the Today Widget extension.
I realize I'll probably need do something unconventional or hacky to get this working, so I'm trying to evaluate possible approaches and come up with a relatively robust solution.
Basically, I want to find a way I can call my
updateLocalNotificationsFromCoreData() function right away any time a new event is logged.
If I can't do it every time an event is logged, an alternative would be to trigger the updateLocalNotificationsFromCoreData() function periodically (somewhat frequently) another way. Here are some solutions I was thinking about using, but I don't like any of them:
Do it in AppDelegate when the app is launched (or another state change)
One approach I'm thinking about is running my updateLocalNotificationsFromCoreData()function in AppDelegate somewhere, like didFinishLaunchingWithOptions.
The downside is that it would require the user to open the app periodically. If the user didn't open it much the notification behavior would be inconsistent. I'd prefer a solution where a user could interact with only the Today Widget and reliably get Local Notifications without ever opening the app.
Sync the events to a server and use Push Notifications
I've thought about syncing the data in Core Data to a server, then setting up Push Notifications to the user's phone based on that.
I don't like this, because I want the user to still be able to get notifications without an Internet connection. It also introduces a lot of extra overhead of syncing the data with a server.
Ping a server, and send a content-available Push Notification
When someone logs an event with the widget, I could ping a server. That server could send back a silent content-available push notification to trigger the app to run updateLocalNotificationsFromCoreData() in the background.
I found a similar question (Scheduling local notification from within a Today extension) where one answer proposes a similar solution. Unlike the previous solution, an Internet connection is not needed to receive the notifications, but an Internet connection would be required to make sure the notifications are up to date when a new event is logged.
Background fetch
I thought about using Background Fetch to fetch something arbitrary from a server, then run the updateLocalNotificationsFromCoreData(). This would be a way to trigger the update in the background, although it seems silly to fetch data if that data isn't being used, and seems like something for which an app could be rejected. There also seems to be a risk of the system not calling the background update regularly if the user doesn't open the app much and mostly uses the Today Widget.
Use background location updates
This seems like the dumbest approach, but I thought I would mention it anyway since I thought about it. I could use one of the low accuracy background location update modes to trigger updateLocalNotificationsFromCoreData().
It would require the user to allow location in the background, which would be hard to explain. And, it would require the user to at least move around a few blocks to trigger the function, which could provide an inconsistent user experience. Also, it would increase power consumption of the app for a silly reason.
I'd really appreciate fresh ideas about how I might be able to reliably schedule local notifications when Core Data changes on a device that doesn't have an Internet connection!
Or, if that doesn't seem possible, I'd appreciated feedback on which approach seems to make the most sense.
EDIT: I came up with a new solution. It's not ideal, but I think it's better than these other approaches I was considering. When someone taps the button to log the event, I launch the full app. It's annoying because I have all the data I need at that point to give the user feedback and log the event within the Today Widget without launching the app, but by launching the app I have the opportunity to check and schedule local notifications.
Also, in iOS 9 the annoyance on the user is slightly minimized because the system-wide "back" button will appear and let the user go back to the previous app easily once my app has launched from the Today Widget.
In the future I may try a solution where one of the server-based approaches above is used when an Internet connection is available, and I would then fall back to this system of opening the app only when the network connection is not available and I need to schedule the local notifications within the app.

In iOS, is it possible to start region based geofencing at a particular time?

My iOS app (which targets iOS 8.1+) use location services to determine if a user has entered a particular region during an event. Ideally I would like to enable the geofencing a little before the event and turn it off a little after the event completes. The problem is there is no guarantee the app is running an hour before the event so I turn on geofencing at the point the user registers for the event. This is not the best approach as it means the geofencing is on for much longer than it needs to be.
As far as I can tell, there is no way to "wake up" the app in the background at a scheduled time in iOS. I could use the push notification meant for updating content, but It's not clear to me if Apple would reject such a misuse of that notification.
Any suggestions?
I've been looking into this myself.
If you can arrange a push notification from your backend ("Silent push notification", aka "content-available"), it seems to be a good option. In real-world situations, this seems to give you the best control over the timing. Unfortunately, it won't work if the person doesn't have connectivity. Also, unfortunately, you need a backend that can queue events at a time (not just in response to an input.) If you have such a backend already, and your app is only useful to the user when they have network coverage anyway, this is probably the best option. It seems this an appropriate use of the technology, so Apple should approve.
Another option I'm trying is to use background fetch. You specify a "minimum interval" to avoid too much fetching. Try 50% of the remaining time-to-event as a minimum. Every time the app wakes up (whether in the foreground because the user opened it, or in the background because background-fetch opens it) you can calculate the time-to-next-event, update the fetch interval, or start the region monitoring. You are supposed to use "background fetch" to fetch information from a server, but there doesn't seem to be any requirement to poll a server, you could poll your internal data instead. I haven't fully tested this yet but it seems promising.
You can use significant location change monitoring, which I've read will wake up your app briefly every 15 minutes or less, and you can use the time/location information to decide whether to turn on the geofence. I think this would work well in combination with the above "background fetch": Many hours or days before the event you rely on background fetch, which you then use to turn on significant location change monitoring a few hours before the event. (There's speculation that geofencing is actually more battery efficient than significant change monitoring, but you could choose to assume that other apps on the user's device will already by watching for significant changes, in which case the marginal cost of your app adding itself to the list should be minimal.)
Putting them all together, you could create a sequence of
background fetch -> significant location monitoring -> geofencing
as the time gets closer.
There is also the CLVisit monitoring functionality, it's not understood very well, but supposedly uses less power and is called less frequently than significant location change monitoring. If the background fetch or silent remote notifications aren't working to wake up your app, give this a try, and please report back!
You can't (yet) do a silent content-available local notification (AFAICT). However, perhaps you can schedule up a local notification "Your event starts tomorrow" or something that convinces the user to click the option that starts the geofence. Here's a tutorial on it http://www.appcoda.com/local-notifications-ios8/, the response of action can be UIUserNotificationActivationMode.Background so your geofence can come on (if the user responds to the notification) without bringing the app to the foreground.
It's been 5 to 6 weeks since you asked, do you have your own answer already? Please let me know.

Keep an app active in the background?

I have a volume control app in the iOS store, but one problem that my users have frequently is that the device kicks it for memory control. Is there any way to either force it to stay active (by permission) or to at least alert the user when its no longer active or in danger?
All the answers are under Background Execution in the iOS Developer Library.
Of course, here's the philosophy:
Always try to avoid doing any background work unless doing so improves
the overall user experience.
See Table 3-1 for the types of background execution. There's a category for audio but it requires audio to be played from the app. It does not sound like your app fits in here. So you'll want to look at notifying the user.
You could send a notification to the user when the app falls to background with applicationDidEnterBackground(), or just before it quits with applicationWillTerminate(), supposedly time-permitting.
Running in the background is permitted. I have an app that does it and while the rules have changed and adapting to it has been gut wrenching at times, it is pretty straightforward. In your case, I would think that you could setup to be notified and then just disappear, no? waking from a notification is part of the state changing protocol and you should be able to do that.
As a point of comparison, in Android, background operations like yours would be implemented as services and would have no fear of being terminated. The strangest thing about the way ios chooses to allow background activity is that you are applying for status one time. In Android, I was able to indicate that a single activity should be kept alive when the app is backgrounded, all others could be terminated. There is no way to do that in ios.
I take it my disappear and wait for notifications is probably not going to work for you because there is no way to be notified of volume changes. You must be polling? In which case, you probably are going to have to ask to be kept alive. Would be nice if you could just piggyback on other services, e.g. keep me alive while music is playing.
To answer your other question, yes you will get notified if/when you really are going to get termed, so you could send a notification at that point.

Trigger iOS app periodically

I'm trying to figure out if there is any permissible way to have my iOS app run periodically (say every 4 hours) and grab a users location. I'm aware of three possible ways this might be accomplished:
Local Notifications (Handling Local and Remote Notifications)
The problem with this solution is that when the app is killed after being in the background a while or the phone restarts, then the local notification will fire and give a UI but not actually start the app so I can't grab the location.
Alarms (Configuring Alarms)
As Apple's documentation says:
Note: An alarm is not intended to serve as a UILocalNotification. An alarm requires you to create an event or reminder that is visible in the user’s Calendar or Reminders app. A UILocalNotification is better suited for general purposes that don’t involve the Calendar database.
Therefore, not only would I be going against Apple's recommendation, but I would then have to ask for access to the user's calendar which won't make any sense to the user.
NSTimer (NSTimer)
I could create a NSTimer, but that solution was already answered here as not viable (That was three and a half years ago but I'm guessing the answer hasn't changed).
Are there any other ways in which this might be accomplished on iOS?
I don't know of any way to grab it periodically every X hours, but the Significant Change Location API might work for your use case. It gives you updates whenever there has been a significant change to the users location.
edit
If you app is not running in the background it will relaunch your app.
/edit
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW10
This stack overflow question has a lot of info about this service also:
Behaviour for significant change location API when terminated/suspended?
See the Getting Location Events in the Background section of Apple's Location and Maps Programming Guide. The other methods mentioned in the question wouldn't actually wake the app up, except for UILocalNotification, and then only when the user tapped in in Notification Center.

Resources