Search code examples
ioscordovaaudioaudio-recordingcordova-plugins

PhoneGap/Cordova iOS playing sound disables microphone


I am currently working on a PhoneGap application that, upon pressing a button, is supposed to play an 8 seconds long sound clip, while at the same time streaming sound from the microphone over RTMP to a Wowza server through a Cordova plugin using the iOS library VideoCore.

My problem is that (on iOS exclusively) when the sound clip stops playing, the microphone - for some reason - also stops recording sound. However, the stream is still active, resulting in a sound clip on the server side consisting of 8 seconds of microphone input, then complete silence.

Commenting out the line that plays the sound results in the microphone recoding sound without a problem, however we need to be able to play the sound.

Defining the media variable:

_alarmSound = new Media("Audio/alarm.mp3")

Playing the sound and starting the stream:

if(_streamAudio){
    startAudioStream(_alarmId); 
}
if(localStorage.getItem("alarmSound") == "true"){
    _alarmSound.play();
}

It seems to me like there is some kind of internal resource usage conflict occuring when PhoneGap stops playing the sound clip, however I have no idea what I can do to fix it.


Solution

  • I've encountered the same problem on iOS, and I solved it by doing two things:

    AVAudioSession Category

    In iOS, apps should specify their requirements on the sound resource using the singleton AVAudioSession. When using Cordova there is a plugin that enables you to do this: https://github.com/eworx/av-audio-session-adapter

    So for example, when you want to just play sounds you set the category to PLAYBACK:

    audioSession.setCategoryWithOptions(
            AVAudioSessionAdapter.Categories.PLAYBACK,
            AVAudioSessionAdapter.CategoryOptions.MIX_WITH_OTHERS,
            successCallback, 
            errorCallback
        );
    

    And when you want to record sound using the microphone and still be able to playback sounds you set the category as PLAY_AND_RECORD:

    audioSession.setCategoryWithOptions(
            AVAudioSessionAdapter.Categories.PLAY_AND_RECORD,
            AVAudioSessionAdapter.CategoryOptions.MIX_WITH_OTHERS,
            successCallback, 
            errorCallback
        );
    

    cordova-plugin-media kills the AVAudioSession

    The Media plugin that you're using for playback handles both recording and playback in a way that makes it impossible to combine with other sound plugins and the Web Audio API. It deactivates the AVAudioSession each time it has finished playback or recording. Since there is only one such session for your app, this effectively deactivates all sound in your app.

    There is a bug registered for this: https://issues.apache.org/jira/browse/CB-11026

    Since the bug is still not fixed, and you still want to use the Media plugin, the only way to fix this is to download the plugin code and comment out/remove the lines where the AVAudioSession is deactivated:

    [self.avSession setActive:NO error:nil];