Flutter Run code and play sound in the background IOS - ios

I've been googling for a long time about how to run code in the background for IOS, and for what I have come up with the short answer is that you can't. And the long answer that you can but is limited. I've seen similar apps to the one I am creating so I feel like there should be a way to make it.
So on to the actual app I want to create. I want to create an application that will continuously play a random sound from a list in between a set interval, let's say for this example 30-60 seconds. So randomly every 30<t<60 seconds a sound should play. You can think of it as a positive affirmations app that should play positive affirmations throughout the day. I've seen such apps exist for IOS, I haven't tried them but I assume they should work like that? And when the app is firing the code to play the sound, Ideally I also want it to send information to a server.
I am using "Flutter Background Service" and "AudioPlayer" packages and have gotten a very very early demo version to work on android where it plays the sound after a random amount of time. And now I want it to work for Iphones also. Since it's not a playlist, I can't use the inbuilt functions for IOS that allows media players to run in the background. For what I can understand is that no code can run for longer then 30 seconds on IOS from when the app goes to the background, or the screen locks. And you can't run background tasks more often then every 15 minutes, or 3 minutes for small work. But that is way to long for the use case I want. I'd want to be able to run the function every 10 seconds to maybe 1 minute at the latest.
So I am wondering, is there a way to get such an application to work for IOS? It feels like it should be possible somehow. I don't really care if you have to "play dirty" to achieve it, and I don't know if it matters or not but I am not planning on publishing the app to the app store. It will only be a private app for me and a few friends.
One way I've been thinking about is maybe use push notifications from a server to trigger it. But I'd rather not have to resort to this if I can help it, if it even is possible to have a push notification to run code/trigger functions in the background?

Related

Playing a sound periodically in the background on iOS

I'd like to play a sound periodically while the app is in the background but after doing some research it's not certain if this is possible. Before I give up or waste too much time trying I want to double check with the community if this is really possible or not.
I figured out how to enable playing sounds while the app is in the background but the app is still eventually killed and the timer stops firing (there's a 10 minute period it runs in suspended mode if I use beginBackgroundTask: but that's not enough). Other ideas I had:
1) There appears to be a "background fetch" mode which could maybe be used like a timer but this is a hack and may be rejected by Apple.
2) Loop blank audio in the background or some other looping part of audio API's to keep the app alive? Again Apple may reject that even it's possible.
3) Enable the location API to keep the app alive and play audio. Hack again, bad for battery and Apple 99% will reject this.
4) I read somewhere that push notifications could work for this but that requires a complicated server backend and if it's possible that last resort.
Are any of those methods viable or are there others?
You can use scheduled Local Notifications with sounds.

Is it possible to build an alarm clock such as the built in app from Apple?

A lot of todo-list apps such as Wunderlist offer some kind of reminder feature which usually just fires off a notification.
But I have never encountered an app that offer a similar notification view as the built in preinstalled alarm clock. You know, that locks the phone and offers a snooze option.
This makes me wonder if the alarm clock functionality that is built into the preinstalled iOs app from Apple including setting time or add a snooze button etc is only available for that particular app?
Since I'm a designer without any coding skills I only want to know if it possible or not.
Unfortunately this is unavailable for developers. You can check all of alarm clock apps in AppStore, all of them are using the standard local notifications. Which will fire once and that's all. You can of course set your custom sound and change couple of options, but it will never work like one build in Clock app inside iPhone.
You can read more about local notifications in Apple documentation: https://developer.apple.com/reference/usernotifications/unnotificationrequest
I figured Alarmy is constantly playing (when there is an alarm set up) a silent sound in the background. Like Spotify, but silent. This keeps the app active all the time. I came to this conclusion by logging the result AVAudioSession.sharedInstance().isOtherAudioPlaying (Swift 4) in my own application. Whenever Alarmy is terminated it returns false, whenever Alarmy is running in the background it returns true. Same thing happens for the app linked by Ernesto Elsäßer.
I used the same technique and I also used this pod to trigger a function when the time comes and start the real music.
I did this for testing and am not going to make an app out of it because playing silent sounds in the background is against Apple's rules. I don't know how Alarmy (or other apps that use this same method) got away with it.
Some related questions:
How do you constantly run in background?
App “Alarmy” is able to play iTunes song from background state… How?
Wake up application in background using AudioSession like Alarmy iOS app
Also you can check this article out.
This app seems to do exactly this, but I have no clue how ...
I tested it, and it managed to start playing music on a locked device at an arbitrarily chosen time, and for way longer than the 30s timeframe allowed for notification sounds. Further, the music is streamed from an online radio station, meaning they found a way to ...
wake up the app from a scheduled notification without user interaction
create a socket connection to a radio station in the background
start playing sound in the background for an indefinite amount of time
I also tried out the alarm in Airplane Mode, and it still played a locally stored backup song, so it probably doesn't abuse the VoiP background mode or push notifications, but really is triggered by a local notification ...
So although I can't tell how, it looks like there is an App Store Review-proof way to create a real alarm app.
(I am not affiliated with the developers of this app, just did some research on what's possible.)

IOS (Swift) Background speech

I'm writing an exercise app that runs a series of timers back to back that are determined by the users exercises and the times they have entered for them e.g. push UPS for 30 seconds, squats 20 seconds...
When the timer reaches zero, the app speaks the next exercise, and starts the next timer.
The app also allows the user to play music from playlists whilst they exercise, so I have set the Audio background mode in capabilities in swift.
When in the foreground, everything works as expected, and the times, and speech fire when they are meant to, however, when the app is backgrounded, only the music continues and everything else stops.
I understand that Apple have strict rules on background processes and multitasking, but I have downloaded a number of apps that seem to work fine in the background and continue to speak the intervals as they become due (Seconds Pro, Onyx Timer etc.)
I have researched this for days, but cannot come up with an answer, background fetching doesn't seem to be reliable enough for a time based app, as you can't guarantee when it will fire, I've also looked into local notifications, but they don't allow speech when they trigger, just a short sound, they also have a limit of 64 notifications, which limits the amount of intervals the user can set
I have set the app to keep the screen awake whilst the timer screen is running, but this means you have to keep the screen on whilst you train, which in turn will add an unnecessary drain on the battery, which seems to go against everything Apple is trying to accomplish with the limited background activity
Push notifications seemed like one solution, but this would mean I have to setup some sort of external server and surely this would be interrupted if the user didn't have an Internet connection.
I have read multiple threads about people running a silent audio stream in the background to keep their app alive in the background (not approved by Apple), but my app already plays audio in the background and has no effect on the rest of the app being suspended?
How would I go about achieving this?
I have thought of a workaround, but I don't know if it's good practice, or if it will get the app kicked if I try to upload it to the app store
My solution was to queue my speech based on the time set in each timer
for timer in 0...timersArray.count{
let sentence = timer.speech
let speechUtterance = AVSpeechUtterance(string: "\(sentence)")
speechUtterance.postUtteranceDelay = timer.time
synth.speakUtterance(speechUtterance)
}
Then the speech would just trigger at the appropriate times, even though the timer wasn't running in the background
When I ran this code, it worked as expected and the speech triggered when the timer would have finished (just as if it was running)
When running this code though, I noticed that not only did it trigger the speech at the correct time, it also kept my app running in the background, which is exactly what I wanted in the first place.
Is this allowed practice, or will it get booted from the store?
As my app plays music in the background and has the audio capability set, is there a way I can use a similar approach, but with the music in the background, rather than the queued utterance approach.
I tried with MPMediaPlayer, AVPlayer, and AVQueuePlayer, but nothing worked, the music played in the background, but the rest of the app stopped
If I set "Does not run in background" to "Yes" in the Plist.info, the app will now run when the screen is locked, it still won't run in the background though?
There are so many apps in the App Store that seem to run happily in the background, I can't believe it's this hard to get it to work?
A number of the ones I have tried, are not listed under notifications, so I know it's not a local notification, they also work in airplane mode, so it can't be remote push notifications

Uploading video files while iOS app is in background?

I'm currently working on an iOS app which involves recording and uploading videos (from the built-in camera) to a server.
It all works reasonably fine and dandy, but for a new version, the customer has requested a new feature: continuing this process without needing the app to up on the screen, and active.
At present, you record a video, it's stored as an MP4 on the file system, and a background thread uploads the file to the server. This all happens while the app is open, culminating in a screen which essentially tells you to wait until the process has finished.
If you press the home button to "minimise" the app (I'm not fluent in iOS terminology, forgive me), currently all upload processes are paused. The customer wants to have it so that you can minimise and do something entirely different as this process continues, with a notification being shown once the uploads are complete.
My understanding is that iOS offers a few special cases for downloading, streaming music and location stuff.
Supposedly once upon a time you could obtain ten minutes or so of background time while your app was minimised to finish tasks - after which time iOS would forcefully pause everything until the app was front and active again. This apparently has been changed in newer versions of iOS meaning you can't rely on a specific figure anymore - but ten minutes wasn't really good enough anyway.
I can think of hacky ways of abusing the above features but I'm half-concerned Apple might discover this during the iTunes submission process. Really I'm looking for a cleaner method - how do I continue uploading videos while the app is minimised?
I am assuming there's a solution - Dropbox can handle this situation?
Surprisingly I got somewhere with this, despite quite a few guides suggesting it was virtually impossible and even Dropbox admitting it has to do a hacky location-based thing.
The code was utilising the NSURLSession class, and for uploading, you use its uploadTaskWithStreamedRequest() method, passing an HTTP request and getting a NSURLSessionUploadTask instance in return.
What wasn't immediately clear to me, however, was that "resuming" that task led to files being uploaded independently from the rest of the app, i.e. when the app is minimised, this task continues until it either completes or iOS forces it to pause.
In a sense I had already achieved what I asked for without realising, however this task can still be interrupted by iOS after a few seconds. The rest of the app is also paused, so communication is hampered until the app is brought back to the front again.
The trick is these two methods:
uploadTaskID = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({})
and
UIApplication().sharedApplication().endBackgroundTask(uploadTaskID)
with these in place, any code after the "begin" function will run regardless of whether the app is minimised, and will do so until the "end" function is called. With a bit of tweaking, I've been able to get files to upload sequentially and post a notification when the process is done.
I haven't seen this solution be hinted at so it might be a bad idea, but it seemingly works.

Background fetch alternatives

I want to my app do some computations and then communicate with external server via HTTP. I would like to perform this operations both in foreground and background. It seems that Background fetch mode is best choice for me but I have some concerns related with this. What is the minimal time interval between fetches? I read somewhere this is 10 min, is that true? I read also that when user force quit fetches are no longer invoked. Is there any walk around to this? Finally, is there any alternative to background fetch? I saw there is Newsstand mode what looks promising. Can I use it for my purposes?
If you use background fetch or another background mode and don't really use it for the intended use, iOS will detect that an kill your app. (the most promising mode for that would be VOIP, but this would't make it into the App Store, as it's a cheat either)
You can start a background task, when your app enters background, what gives you 3 minutes time (iOS 7 and above).
As I did it before, you can schedule a local notification and use it to remind the user, that he should bring the app back into the foreground for more calculations, if he likes.

Resources