An equivalent to an NSTimer for a background Audio app? - ios

I have a video streaming app that is properly set up to play video via AirPlay while the device is locked or in the background. It works great. However, the one thing that doesn't work when the app goes into the background is the NSTimer I use to send an update back to a server once every 10 seconds. I've read through countless posts about NSTimers not working when an app is in the background. There are lots of proposed hacks and kludges, but I didn't find the proper way to do this, or if there even is a proper way.
However, since mine is an audio app where some background processing is permitted, I would expect there might be some way to periodically send a post to a remote server.
Is there a preferred way to do this?
Thanks,
Craig

Related

Background Audio mode with MPMusicPlayerController.systemMusicPlayer

I'm working on an iOS app that uses MPMusicPlayerController.systemMusicPlayer to play songs from Apple Music to the user.
My app should be able to append songs to the Music player's queue based on messages it receives from a server. I have this working with a simple WebSocket connection between the app and the server, but as soon as the app enters the background the socket is automatically closed (which makes sense).
Because the actual music playback is done by the Music app, I can't use the Background Audio background mode to keep my app alive. Is there a way around this?
Things I have already considered (and why I don't think they will work):
Remote Notifications are throttled too slow to be of any real use
Background App Refresh is also too slow
PushKit / VoIP (the app isn't a VoIP app)
Playing "blank" or nearly silent audio over the actual audio which seems too "hacky" and likely won't pass app review
Using background location tracking (again, almost certainly won't pass review)
Ditching systemMusicPlayer completely and using AVAudioPlayer with the Apple Music API (this would be reinventing the wheel a little bit and would force streaming even if the media was downloaded)
Using applicationQueuePlayer and just forcing the user to stay in app (this would be a bad user experience imo, they should be able to listen in the background)
Any help would be appreciated, thank you!
In iOS 15 and later, you should be able to just set the background plist flag for your app, and then just use ApplicationMusicPlayer.
https://developer.apple.com/documentation/musickit/applicationmusicplayer

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.

NSTimer run in background - needs to fire every hour

I created an app that will send text messages through an API similar to Twilio, and I have an NSTimer that fires a function every set amount of time. The problem is that if you press the home button, it will totally stop the timing, which defeats the purpose.
I have read that it is possible to have your phone play a mute sound until closed to make sure it still runs in the background, but I can't find a resource on how to do this. Here is an example: To run NSTimer in background
If anyone has any information on how to do this, I'm sure it is very simple, and I very much appreciate the help.
Thank you.
If you set up your app as a background sound playing app then yes, it is technically possible to play a "silent sound" in order to keep it active in the background, but your app will be rejected by Apple if you do this.
Apple expressly forbids what you are trying to do.
You should look at using scheduled local notifications. Those will alert the user, who can bring your app to the foreground and let it perform the desired task.

Background process for sending data to server

Is it possible to run a background task on iOS that uploads data to a server every minute or so, like a service on Android?
Not like Android. Only when the app is running in the foreground.
Nothing like a service but there are certain categories of apps that can be run in the background for an extended period- In addition to VOIP that #lorean mentioned, there are others- audio, location, newsstand , external accessory -https://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
. So if your app fits into these categories, then you are set.
Otherwise, you could also run your app as a background audio app by playing silent audio in a loop in the background- but there may be issues trying to get it through the App Store. For instance, you may be required to explicitly inform the user that audio will be played.
There's no way to do it as service except some special cases provided by ios. But you can simulate it. This post answer how to:
https://stackoverflow.com/a/19121250/2835520
I hope it's gonna help!

How to handle AVPlayer errors while the app is running in the background?

I am using AVPlayer to play an audio stream, and it's possible to keep it playing in the background. I'm wondering how could I handle a situtation where the user loses internet connectivity, so that I could provide some feedback or maybe try to re-establish the playback after some seconds.
EDIT: I know that the question regards AVPlayer, but if you have an answer with MPMoviePlayerController it might be useful as well. Right now, by using MPMoviePlayerController, I'm trying to get the MPMovieFinishReasonPlaybackError case of the MPMoviePlayerPlaybackDidFinishReasonUserInfoKey, by subscribing to the MPMoviePlayerPlaybackDidFinishNotification but if f.e. my audio is playing in the background and I turn airplane mode on, I never get this notification; I only get MPMovieFinishReasonPlaybackEnded, and I don't know how to separate that from the case that the user stops the audio himself.
I tried looking around for the actual source but I remember reading somewhere that if the audio playback stops (for whatever reason) it kills the background thread. The person writing about the issue talked about possible feeding the stream some empty audio content to keep the thread alive. You might be able to send a local notification from a call back error notifying the user that the audio experienced an error and will have to be manually restarted from within the application. Haven't played around with the API enough to know which callback is the best one to use in this case. If I find the link I'm looking for I'll update.
EDIT: Here's Grant Pannell's take on audio streaming and multitasking.

Resources