Exporting videos with AVAssetExportSession in background the background - ios

I am working on an iOS 8 app which records a video, modifies it using AVMutableVideoComposition and exports the result with a AVAssetExportSession calling exportAsynchronouslyWithCompletionHandler.
Things work fine as long as the app is in the foreground. When a user pushes the home button and sends the app into the background before the export has finished however, the following error is raised:
Error Domain=AVFoundationErrorDomain Code=-11847 "Operation Interrupted"
UserInfo=0x174271c40 {NSUnderlyingError=0x170246c90 "The operation couldn't
be completed. (OSStatus error -12125.)", NSLocalizedRecoverySuggestion=Stop
other operations and try again., NSLocalizedDescription=Operation
Interrupted}
It looks like others have experienced the same error with Audio: AVAssetExportSession working in background
I have tried all kind of things like requesting more time for the execution using beginBackgroundTaskWithExpirationHandler (does not work because the export is interrupted before the time runs out), adding Audio as a Background Mode in the app capabilities (does not work, maybe because I use AVMutableVideoComposition?), starting the export in a custom queue outside the main thread, but nothing works.
Even trying to restart the export in case it has not completed when the app enters background fails. I tried to listen to UIApplicationDidEnterBackgroundNotification and restart the export after the app is already in the background but I get the same error.
The discussion in this thread hints that it could be because AVMutableVideoComposition can not be used in the background:
Starting AVAssetExportSession in the Background
Is this still true for iOS 8? Is there any workaround or does anyone know how I could accomplish the desired functionality (editing and exporting a video a user has just recorded even if he sends the app to background)?
Any help is highly appreciated, I have spent many hours on this problem.

iOS 13 tested. Play silent sound while exporting.
Audio session should be configured like:
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay])
try AVAudioSession.sharedInstance().setActive(true)
Background mode required.

Unfortunately, it is still true for iOS 8. You can not export when app is in background but it is possible to start export as soon as it comes to foreground.
Just save the AVMutableCompostion before your app goes to background. This can be done in applicationDidEnterBackground. Then you can start export again in applicationDidBecomeActive.
Note: You have to start the export all over again. It can not be resumed if not finished before entering background.

Related

Play Webrtc Audio message when IOS app is in background

Hi this might be duplicate to this question. But I did not find right answer for this. I have developed an app like zello push to talk using react-native. I want to play the audio message automatically without any user interaction when the app is in background or killed. Whenever any user sending real time audio message, I am sending a push notification to ios app and after receiving notification I am invoking a function which establishes socket connection with the webrtc server and then join in the room in which webrtc audio broadcasting is happening. Now I checked that socket is connected and also joining in room successfully done after receiving push notification when app is in background. But there I could not hear any audio and received following error message.
AURemoteIO.cpp:1668 AUIOClient_StartIO failed (561145187)
Then I have set AVAudioSessionCategoryPlayback and that error gone. But this time also did not hear any audio sound.
The app is working fine when it is in foreground. I am using react-native and this is happening for IOS app only. Any help is appreciated. In xcode I have enabled push-notifications, background-fetch, background-airplay etc.
You need to set your app Capabilities Background Modes (Audio and AirPlay).
To Enable this select your iOS project in iOS then go to Signing & Capabilities tab.
Check for Background Modes and select Audio, AirPlay and Picture In Picture option.
Also, set your AVAudioSession category to AVAudioSessionCategoryPlayback and set it active.
Example:
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, options: AVAudioSession.CategoryOptions.mixWithOthers)
NSLog("Playback OK")
try AVAudioSession.sharedInstance().setActive(true)
NSLog("Session is Active")
} catch {
NSLog("ERROR: CANNOT PLAY MUSIC IN BACKGROUND. Message from code: \"\(error)\"")
}

iOS Audio/Sound won't play in background with background mode active

My app (made with Flutter but this should not matter) has something like a timer functionality that makes a tick sound in regular periods (between 10s and 3min). I have the background mode Audio, AirPlay, and Picture in Picture activated and the following in my Info.plist.
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
but the audio will still stop when running in background.
This occurs when running the app in profile mode, when I run in debug mode, the audio continues when running in background.
What can I do to have the audio continue to run in background?
There is a relevant note in the audio_service 0.18.0 README which can help here:
Note that the audio background mode permits an app to run in the background only for the purpose of playing audio. The OS may kill your process if it sits idly without playing audio, for example, by using a timer to sleep for a few seconds. If your app needs to pause for a few seconds between audio tracks, consider playing a silent audio track to create that effect rather than using an idle timer.
Well, unless you did this in native code (Swift/Objective-C), your code is running inside the Flutter engine - probably with some Dart Timer.periodic.
The Flutter engine may be killed off at any point in time when the app is in the background. On Android this can even happen when simply switching to the camera and back to the app afterwards. On iOS usually after some fixed time or on high system load.
In this regard, Flutter (and most other cross-platform toolkits) are very different to native apps.
You can start with the official documentation here: https://flutter.dev/docs/development/packages-and-plugins/background-processes
This may be a good article: https://medium.com/vrt-digital-studio/flutter-workmanager-81e0cfbd6f6e
I don't know enough about iOS but I think there is no easy way to schedule execution in the small intervals you require. On Android something like the AlarmManager can be used.
You can try writing the scheduling code natively and schedule it from the app via a MethodChannel when the period is set.
You can look at these libraries:
https://pub.dev/packages/workmanager (probably can't wake up at the small intervals you need)
https://pub.dev/packages/android_alarm_manager_plus (only for Android)
https://pub.dev/packages/audio_service (may give you some idea on how to achieve background execution on iOS)
Edit:
After reading more about Enabling Background Audio on iOS, it seems to me, that this only works when using
an AVAudioSession. Which you are probably not using. To get this working you need some native code. The audio_service package uses such a session. You can try scheduling with Dart code and playing the sound via the audio_service package. Sounds like it could work but I have no experience with this package.
Please, pay attention to the answer from #RyanHeise – he's correct on the point of using AudioSession: in background you should play either sound or silence. As soon as audio will be paused, app can be suspended.
Also, Important Note: when app entering background, scheduled timers will pause. That's why you might think it stopped working. Do not use scheduling via Timers on background - rely on events from the system.

Background Audio is enabled but not needed

following the examples, I enabled the Background Audio capability in my app, even though I do not need it. I want simple playback only, with midi triggering sounds (sf2) from the app bundle only, in foreground only. I got everything working and submitted my first version to the App Store and I get complaints from the reviewer saying that if I don't use background audio (so they can't test it) then I should switch it off in the Capabilities. If I do that my foreground audio triggering stops working. Can anyone help in what is the proper way configure AKSettings and the app in this case, so I could pass the app store review?

iPhone indefinite background exectuion Xcode mystery

I am writing an app for personal use that needs continuous background execution. Apple tries to make this difficult, but I found that declaring that my app uses background location updates and then creating background task (with no content, just a blank task) allows my app to run indefinitely when I run the project from Xcode. I do not understand why this works. I noticed that after about three minutes, when presumably the task is supposed to be terminated, I get the following error:
Can't endBackgroundTask: no background task exists with identifier 174256fe0, or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
After this message, the app continues to run in the background normally. So, it seems that this indefinite execution is a bit of an exploit, which I'm fine with because I just want to make the app work.
However, when I run the app from the phone (i.e. not pressing the run button in my Xcode project), the background execution seems to stop after 3 minutes. This is a problem, and I can't seem to figure out why execution continues in one case but not in the other. What is the difference between running an app normally and running it through Xcode? Is there a simpler or better way to get the indefinite background execution I'm looking for given that I'm not trying to get this app published to the app store?
Since you're not submitting to the store - why not try this:
Enable the app for background audio services. Then, just play a silent audio file in the background on a constant loop?
The difference is that you are running through Xcode. Normal background limits are removed when running through the debugger.

iOS: Does force quitting the app disables background upload using NSURLSession?

The question is around NSURLSession and NSURLSessionUploadTask.
I'm uploading large files to server and noticed that when I force quit the app the whole background upload just stops. However, when upload starts while app is running through the Xcode/debugger, then my upload completes just fine even when I stop the app running via Xcode 'stop' button. I suspect that force quitting the app using Xcode simulates an iOS system command and not a user action.
So my question is whether it's true that iOS would immediately cancel NSURLSessionUploadTask when user force quit the app?? For some reason I would at least expect an error callback to the app, however nothing happens.
I can confirm now after a bunch of testing that background task will run ok if the app is just put into background. However, if user force quit the app manually, then iOS cancels all scheduled background tasks. So next time the app is launched I'm getting all the callbacks to the delegate with the error code of a canceled task.
Hope it helps someone looking into the same thing.
From Apple's docs about background execution:
If tasks have not yet finished and the system terminates your app, the
system automatically continues managing the tasks in the background.
If the user terminates your app, the system cancels any pending tasks.

Resources