[iOS Solved, andoid?] Sound Effects, not audio stream?

Hey guys! I found a topic ([How to add sound effects/tunes on ui events?][1]) which I was hopeful for. Only thing is it suggests to use the cordova media plugin. The issue I’m having is within my workout app, I need to be able to notify a user via a sound to continue BUT when I do this using the media plugin, it turns off all other sounds i.e.: spotify, iTunes, and such.

Has anyone come up with an alternative that allows for a sound to be played WITHOUT disabling the native audio? I’ve been trying to play with Audio tags and HTML5 stuff, however on iOS those seem to disable the native audio as well.

I’ve got a last resort which uses javascript to hold the bytes of the audio then plays that as a stream and that seemed to work great in the mobile safari browser with spotify running but i have yet to try and implement it within the app.

Any suggestions on how to accomplish this would be wonderful. I am wanting to use Crosswalk as well so as far as platform compatibility lets not worry about that. Any ideas?

Update:

I tried the audio stream loading idea and it still stops the background music playing. There HAS to be a way to do this!

Solved!

Okay so what I had to do was use the cordova media plugin, however I ended up modifying the actual plugin source…

I’ll explain it as best I can and give you the snippets I had to change, there are better ways to do this such as adding a variable to pass to set how the audio gets played but my app doesn’t need the defaults.

iOS splits audio into a few different categories. The one we are worried about is the one that the cordova media plugin uses by default. It’s called ‘AVAudioSessionCategorySoloAmbient’. What we want is ‘AVAudioSessionCategoryAmbient’

Now for the change in the source to work you have to tell it to be an ambient sound (meaning it plays WITH the background music such as spotify and other apps) before it prepares the sound to be played. If you go to the plugins folder within the xCode project and locate CDVSound.m, this is where we will change stuff.

Find the function: startPlayingAudio

We are going to replace this entire function with my code (found in this paste bin) : http://pastebin.com/UY2ZpBn4

Compile your app and it will play your sounds OVER the background music.

NOTE: Apple will most likely decline your apps submission if you are doing this will full audio. It is meant to be for short sound effect like sounds. The example they give is ‘such as a virtual piano that a user plays while the Music app is playing’.

I have yet to test this all on android, will update with more results. I hope this helps some lost soul out there.

Hi @nnnnnorthhhhh - did you ever figure this out on Android? Thanks!

I don’t have an android device to test it on, so no, but once i have access to one I’ll have to figure it out. I’ll be sure to updated this topic when I do. I imagine it’s similar, though. @rajatrocks

Thanks. I’m using the cordova media plugin to play sound effects in my app. On Android, the sound effects were playing loudly even when the phone ringer was on mute or vibrate, because the plugin was using the STREAM_MUSIC audio stream type. So I made the following change:

In platforms/android/src/org/apache/cordova/media/AudioPlayer.java in the loadAudioFile function, right before this line:

this.setState(STATE.MEDIA_STARTING);

I added this line to change the audio stream type for all my locally loaded sound effects:

this.player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);

Now the sound effects in my app use the phone/ringer volume and mix in with any media that’s currently playing.

btw - the different Android stream types are all listed here: http://developer.android.com/reference/android/media/AudioManager.html

Now on to iOS to see what needs to be done there. Will try out your code if I need it!

1 Like

OK, so on iOS I did the following:

In my app, I called media.play with the playAudioWhenScreenIsLocked option set to false:

media.play({playAudioWhenScreenIsLocked:false});

Android ignores this. On iOS this handled using the device volume and turning off my sounds with the Silent switch. As you noted, this didn’t solve the problem where my sound effects killed any background audio (iTunes, Spotify) that might be playing. To do that, in platforms/ios//Plugins/org.apache.cordova.media/CDVSound.m, I searched for the one instance of AVAudioSessionCategorySoloAmbient and changed it to AVAudioSessionCategoryAmbient. That seemed to do the trick. So the changed line looks like:

NSString* sessionCategory = bPlayAudioWhenScreenIsLocked ? AVAudioSessionCategoryPlayback : AVAudioSessionCategoryAmbient;

Now it behaves like I want it to and mixes in audio just fine. I noticed in your pastebin that you had moved the call to prepareToPlay to after the setting of the sessionCategory (and that someone else had recommended that here: http://stackoverflow.com/questions/10377959/on-ipad-why-does-avaudiosessioncategoryambient-stop-the-music-playing-in-ipod). It seemed to work without doing that (and I actually think they’re referencing two different things that happen to have the same name), so I didn’t change it.

For reference, the various iOS audio session categories: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html#//apple_ref/doc/constant_group/Audio_Session_Categories