Simulate phone call on hands-free to play audio files with AVAudioPlayer - ios

Many older cars have no option to play music from external bluetooth devices (A2DP), they are only able to handle phone calls (hands free). But some navigation apps are able to play sounds simulating a phone call. This way, the radio/CD-player gets interrupted as long as the navigation app plays the sound.
Has anyone an idea how to do this with AVAudioPlayer? Or another method? I could not find any infos related.
That's what I have so far, but I guess I'm completely wrong..
NSUInteger optionsFlag = (AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers);
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback withOptions:optionsFlag error: nil];
NSURL *soundFileURL = #"/path/to/soundfile.wav";
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
[player play];

Related

AVAudioPlayer cannot play on background when Youtube playing

I make an alarm feature for my app, at the time I setup for alarm fire I can play a music track with AVAudioPlayer, it worked well on background mode. But if at this time I opening Youtube app and playing a video then the AVAudioPlayer not work.
Please tell me why this happen and how to resolve this issue, how to play both at the same time
This is code I implement:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:#"remind2"
withExtension:#"mp3"];
avSound = [[AVAudioPlayer alloc]
initWithContentsOfURL:soundURL error:nil];
[avSound setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[avSound prepareToPlay];
[avSound setNumberOfLoops:10];
[avSound setVolume:1.0];
[avSound play];
Thanks!
This is happened because of Youtube app also set property "UIBackgroundMode" property in plist. And even if you check any of other Music app like gaana, savan, etc. this will happened in all of the music app.
Replace this line
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
by this:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
and I resolved my problem
It takes me two days to put the right questions to this problem, I only find the solution when i ask Google why Youtube stop my audio stream and this result search help me
AVAudioPlayer turns off iPod - how to work around?

Why does AVAudioPlayer does not play?

We developed this iOS scenario:
1) iOS App schedules local push notification
2) Push is a trigger to start AVAudioPlayer audio playing - even if the iPhone is locked (app in background)
Now there are two scenarios:
a) Time difference between push scheduling is more than 3 hours:
Audio does start playing after unlocking and starting the app
b) Time difference between push scheduling is less than 3 hours:
Audio does start playing even without unlocking
We want case b as default case. Does iOS stop/freeze our application after some hours? Interesting: On indian devices there does not seem to be case a - even if time difference is more than 12 hours.
Any ideas?
Thanks so much!
Did you integrate background execution? Otherwise the app will be suspended after a while.
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Once didReceiveLocalNotification method triggered in appdelegate, then trigger one method in appdelegate or in global then use below code to play audio file using AVAudioPlayer in background or device lock
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#“filename”
ofType:#“type”];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL
error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
player.numberOfLoops = -1; //Infinite
[player prepareToPlay];
[player play];

iOS - Sending one audio stream to the built-in speaker and a different stream to a Bluetooth HFP speaker

I am building an alarm clock app which works in conjunction with a physical Bluetooth device. I need to send one audio file (a song selected from the iTunes Library) to the built-in speaker and a separate audio file to the Bluetooth device (which is, effectively, a Bluetooth HFP speaker) at the same time.
My first thought in completing this would be to use AVAudioSession's new AVAudioSessionCategoryMultiRoute, but iOS 7 does not detect my speaker as a possible route; it will detect either the built-in speaker or the HFP speaker, but it will not detect both simultaneously. Detecting both is required to send two files at the same time.
My second thought was to use AVAudioSessionCategoryPlayAndRecord (even though the app has no need for a microphone) and to use overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker and overrideOutputAudioPort:AVAudioSessionPortOverrideNone like so:
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"alarm"
ofType:#"m4a"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
self.bluetoothAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL
error:nil];
self.bluetoothAudioPlayer.delegate = self;
[self.bluetoothAudioPlayer play];
NSError *error = nil;
NSURL *selectedSongURL = [self.selectedSong valueForProperty:MPMediaItemPropertyAssetURL];
NSLog(#"selectedSongURL: %#", selectedSongURL);
if (selectedSongURL) {
if (![[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error]) {
NSLog(#"overrideOutput error: %#", error);
}
self.internalAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:selectedSongURL error:nil];
self.internalAudioPlayer.delegate = self;
[self.internalAudioPlayer play];
}
After this alarm is silenced, I run [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil]; to reset the override call.
However, this doesn't work because iOS just puts both audio signals on the same speaker.
Is there a way to send one audio stream to a Bluetooth HFP speaker and a different audio stream to the built-in speaker?

AVAudioPlayer Does Not Respect Mute

There are other topics on this but I can't comment in them, and I've tried all the approaches listed.
My app has a song that plays when it opens, but hitting the mute on the iPad has no effect (it should mute the song).
Here's my code where I start the sound:
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"intro_theme" withExtension:#"wav"] error:NULL];`
[audioPlayer play];
And here's the various approaches I've tried:
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];
UInt32 sessionCategory = kAudioSessionCategory_AmbientSound;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
Other people seem to be able to get AVAudioPlayer to respect the mute option - any ideas?
Have you tried the category AVAudioSessionCategorySoloAmbient?
per Apple's docs:
When you use this category, audio from other apps is silenced. Your audio is silenced by screen locking and by the Silent switch (called the Ring/Silent switch on iPhone).
Here is a solution:
I delayed playing my audio using an NSTimer until 1 second after the call to setCategory. This is working on iPad 3 & iPad 1 (haven't tested on 2).

AVPlayer streaming audio in background

I have a problem with the AVPlayer playing in background mode, like a lot of people here and everywhere on the web. I've done what I think is supposed to work, but is still doesn't... I think my problem might be where I set and use my AudioSession and AVPlayer.
1) The "audio" key is in UIBackgroundModes of my Info.plist
2) AudioSession set like this in AppDelegate (initialised in didFinishLaunchingWithOptions):
AVAudioSession *audio = [[AVAudioSession alloc]init];
[audio setCategory:AVAudioSessionCategoryPlayback error:nil];
[audio setActive:YES error:nil];
3) I use an AVPlayer (not AVAudioPlayer) also implemented in AppDelegate. (initialised in didFinishLaunchingWithOptions, after the AudioSession), right after the AudioSession
// Load the array with the sample file
NSString *urlAddress = #"http://mystreamadress.mp3";
//Create a URL object.
self.urlStream = [NSURL URLWithString:urlAddress];
self.player = [AVPlayer playerWithURL:urlStream];
//Starts playback
[player play];
And still, the audio is suspended everytime the app goes in background (when I press the "Home" button).
By the way, the problem was just with the simulator. Works fine on the iOS devices

Resources