My app uses device's microphone and manages AVAudioSession.
I want to check if there is other app playing audio, if so, I want my app to stop using microphone & stop my audio session, this is what I tried (the following code is periodically triggered to check is there other app playing audio):
BOOL isPlayingWithOthers = [[AVAudioSession sharedInstance] isOtherAudioPlaying];
if (isPlayingWithOthers) {
[[AVAudioSession sharedInstance] setActive:NO error:error];
}
I run my app, then, I open "My music" app, and playing a music, the above code is executed but I get the following error:
Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
Why I get this error? How to solve it in my case? (My app is running on iOS7 and above)
Related
I am working on a VoIP app. For that I had set the category of AVAudioSession to AVAudioSessionCategoryPlayAndRecord.
All the app functionality was working fine till now.
Then we had a new requirement where within app when the voice call is going on, user can play one video embedded in WKWebView.
Now when user plays video from WKWebView, video plays successfully and the volume of video is also as expected. But when user stops/pauses the video then voice call gets disconnected.
So I came to know that WKWebView runs in different process than the app, so in order to make my app's audio mixable with WKWebview I have to set the AVAudioSession as mixwithOthers.
I have done that with the following code...
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *errorInSettingCategory;
BOOL success = [session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions: AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionAllowBluetooth error:&errorInSettingCategory];
Now after playing video form WKWebView I am able continue with my voice call.
But this approach introduced the new bug.
As now the AVAudioSession is mixable, volume of the video from WKWebView is quite low and app's audio (voice call audio) is quite dominant.
I have tried different setcategory options but with no luck.
I want to have volume of app's audio and volume of WKWebView's video at same level.
Thank you for any help.
Try setting the duckOthers property of your AVAudioSession to false:
https://developer.apple.com/documentation/avfoundation/avaudiosession/categoryoptions/1616618-duckothers
2017-02-24 14:56:44.280 PropertyManager[10172:5336578] 14:56:44.280 ERROR: [0x1a0a24000] AVAudioSession.mm:692: -[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
2017-02-24 14:56:44.281 PropertyManager[10172:5336578] error === Error Domain=NSOSStatusErrorDomain Code=560030580 "(null)"
PropertyManager was compiled with optimization - stepping may behave oddly; variables may not be available.
Your error log is very succinctly self-expressive:
Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session
It tells you the problem and also the solution.
Right now you're doing something like this:
[[AVAudioSession sharedInstance] setActive:NO
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
error:nil];
You should however, first stop the audio player instance and then set the activation status to Yes or No.
[yourAudioPlayer stop];
[[AVAudioSession sharedInstance] setActive:NO
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
error:nil];
Refer to Apple Documentation to see values of enum AudioSessionSetActiveOption.
Also see: Apple Documentation on setActive:withOptions method
As for your second error
PropertyManager was compiled with optimization - stepping may behave oddly; variables may not be available.
see this excellent answer.
#NSNoob is 100% correct. The player (or something else) is still active.
More from dani-mp. He said:
I'd say that pausing the player is not a synchronous operation, so we
shouldn't be deactivating the session before knowing that the player
has been paused (see the response in this thread).
A solution for this problem could be that we listen to changes to
timeControlStatus and deactivate the audio session once the player has
really been paused.
The answer in the thread says
This error indicates that something in your app is still using audio
I/O at the time when the AVAudioSession setActive:NO is being called.
It’s impossible to say which object without more information, but
sometimes it’s the result of calling an asynchronous stop method on a
player of some sort and not waiting for the notification that the
player has stopped before deactivating the audio session.
Make audio player to stop before making recording session false.. if u suppose to make audio player to be nil.. remove that line.. it works for me..
I've read many posts and articles and am having no luck playing audio when iPhone is in silent. I'm using react-native-sound which uses AVAudioPlayer under the hood. The following calls succeed without any luck with sound coming through when in silent.
NSError *setCategoryError = nil;
BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
if (!success) { /* handle the error condition */ }
NSError *activationError = nil;
success = [audioSession setActive:YES error:&activationError];
if (!success) { /* handle the error condition */ }
Any suggestions?
Resources:
https://developer.apple.com/library/content/qa/qa1668/_index.html
I am struggling with this as well. I don't think it is totally possible. I can have sound play in silent mode when the app is in foreground then continue playing while it is in the background, but I don't think iOS allows you to trigger a sound to play while the app is in the background and in silent mode. I am using local notifications to trigger the sound to play.
Some people have had luck setting 'Application does not run in background' to YES in the info.plist which keeps the app in the foreground when someone locks there phone with the app still in the foreground but I need the app to work if the phone is locked when the app is in the background.
Currently the only solutions I know of are to play a silent audio track then tell it to keep it active after playing (to not waste cpu/battery). See link here. Apple normally doesn't approve of this in app review. Or to use location updates.
My application plays music and records from mic at the same time. Recording can be started after playback is started or before playback is started
And now I want to stop recording but keep playback running at the same time.
How can I do this?
I can stop recording and playback by using
[[AVAudioSession sharedInstance] setActive:NO error:nil];
But the issue is: I want to stop recording only.
I tried to change category to AVAudioSessionCategoryPlayback using the following code
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error]
but that doesn't stop recording.
I solved the issue by explicitly stopping all recording activity without touching AVAudioSession at all.
The following warning
AVAudioSession.mm:623: -[AVAudioSession setActive:withOptions:error:]:
Deactivating an audio session that has running I/O. All I/O should be
stopped or paused prior to deactivating the audio session.
helped me to identify the issue.
Initially I forgot to call the AudioOutputUnitStop method of AudioUnit framework. Because of this recording process was still running and audio session were indicating that.
I am using SpeechKit from Nuance to transcribe text from video as I record it. However, when SpeechKit is active, AVAudioSession generates the following error:
AVAudioSession.mm:646: -[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
Disabling SpeechKit lets me record and preview the video. Enabling it generates the transcribed text, but doesn't record the video.
I have put a sample project online at:
https://github.com/jeffreality/iOSVideoTranscriber
My goal is to save the video with audio, as well as have a transcription.
You can move the following line to viewDidLoad:
#if ENABLE_TRANSCRIPTION
[SpeechKit setupWithID:#"Your ID"
host:#"dfo.nmdp.nuancemobility.net"
port:443
useSSL:NO
delegate:nil];
#endif
This ensures that speechKit has already been set up when you create your own capture session in viewDidAppear.
SpeechKit delegate method recognizerDidFinishRecording is called when the recognizer stops recording audio. It is automatically called when a silence is detected, or manually called when you do [voiceSearch stopRecording]. When this happens, your own recording has not finished, it needs time to save the audio file to disk, and the error message says all i/o should stop prior to deactivating an audio session. You can see a log by the sdk release audio session 1, which I think is deactivating a session and release it. So I think you should add this in the above method.
[[self.session.outputs[1] connectionWithMediaType:AVMediaTypeAudio] setEnabled:NO];
The output is AVCaptureMovieFileOutput you set up earlier, and connection is an audio connection, doing this seems to make the error disappear.