How can stream Audio when iPhone is locked? - ios

I'm working on AppRTC for Audio call, It's working fine when app is open. Audio call is not working when device is locked, If wI un-lock device while call and open app, It's start working normally but while it's locked it's not working. (Audio is not passing or playing).
I already added "App plays audio or streams audio/video using AirPlay" in "Required background modes" of plist.
Audio session is also configured. Please check code below.
- (void)configureAVAudioSession:(BOOL)isSpeakerOn
{
// Get your app's audioSession singleton object
AVAudioSession *session = [AVAudioSession sharedInstance];
// Error handling
BOOL success;
NSError *error;
// set the audioSession category.
// Needs to be Record or PlayAndRecord to use audioRouteOverride:
success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
error:&error];
if (!success) {
NSLog(#"AVAudioSession error setting category:%#",error);
}
// Set the audioSession override
success = [session overrideOutputAudioPort:isSpeakerOn?AVAudioSessionPortOverrideSpeaker:AVAudioSessionPortOverrideNone
error:&error];
if (!success) {
NSLog(#"AVAudioSession error overrideOutputAudioPort:%#",error);
}
// Activate the audio session
success = [session setActive:YES error:&error];
if (!success) {
NSLog(#"AVAudioSession error activating: %#",error);
}
else {
NSLog(#"AudioSession active");
}
}
Please let me know if anything is missing or i'd implemented wrongly.
Regards,

Related

Background Audio for iOS Video App

So I was working on a video capture app that plays background audio (from Spotify or Apple Music) and I'm having a small problem where there's a small audio interruption when I open my app while audio is being played.
Here's what I have for allowing background audio to play (located in my didFinishLaunchingWithOptions in my AppDelegate class:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers
error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
Any clues to stopping that beginning interruption? Thanks!!
EDIT
I should also mention after setting the AVAudioSession I am setting my AVCaptureSession. I initialize it then set the properties.
self.session.usesApplicationAudioSession = YES;
self.session.automaticallyConfiguresApplicationAudioSession = NO;
I think the reason of interruption is you are updating category in every case. You may use below function to check and update category only if it is needed.
-(BOOL) checkAndUpdateCategory {
NSError *error;
AVAudioSession *session = [AVAudioSession sharedInstance];
BOOL result = [session.category isEqualToString:AVAudioSessionCategoryPlayAndRecord];
if(!result) {
result = [session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers error:&error];
if(error) {
//Handle Error
NSLOG(#"Error:%#", error);
}
}
return result;
}

iOS how to stream audio to a bluetooth speaker

I want to stream my voice with my iPhone 4 (iOS 7) to a Bluetooth Speaker Device (this one) with the lowest latency/delay possible.
I managed to capture my voice with almost no latency and broadcast it to my speaker through an audio Jack connector but when I pair my Iphone with my Bluetooth Speaker Device it doesn't work. I don't hear anything.
And when I open Youtube in my iPhone the sound is correctly transmitted to the bluetooth Speaker Device. So the problem is not in the Bluetooth Speaker Device but in my code.
Do you have any suggestions or advices ?
Here's the code I put in the delegate class (didFinishLaunchingWithOptions function) to init the audio session :
// configure the audio session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = NULL;
// deactivate session
[audioSession setActive:NO error:&err];
if (err) {
NSLog(#"There was an error deactivating the audio session");
}
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&err];
if( err ){
NSLog(#"There was an error creating the audio session");
}
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&err];
if( err ){
NSLog(#"There was an error sending the audio to the speakers");
}
// Activate the session
[audioSession setActive:YES error:&err];
Then I use EZAudio framework to send audio to the audio device:
/**
Start the output
*/
[EZOutput sharedOutput].outputDataSource = self;
[[EZOutput sharedOutput] startPlayback];

iOS 7 Can't have audio via bluetooth receiver using AVAudioSession

I'm facing an issue using bluetooth for my app on iOS 7.
To be more precise, the bluetooth receiver i'd like to connect to is : http://www.amazon.co.uk/Sony-Bluetooth-Receiver-Enhancement-Smartphone-Black/dp/B00G9YK7LS
Of course the iPhone is paired to the device before I start testing.
My app should just make an audio pass through (from the mic to the speakers) using the EZAudio framework. It works fine using the iPhone headset but not with the bluetooth.
Here's the code I put in the delegate class (didFinishLaunchingWithOptions function) to init the audio session :
// configure the audio session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = NULL;
// deactivate session
[audioSession setActive:NO error:&err];
if (err) {
NSLog(#"There was an error deactivating the audio session");
}
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&err];
if( err ){
NSLog(#"There was an error creating the audio session");
}
[audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&err];
if( err ){
NSLog(#"There was an error sending the audio to the speakers");
}
// Activate the session
[audioSession setActive:YES error:&err];
Then I use EZAudio framework to send audio to the audio device:
/**
Start the output
*/
[EZOutput sharedOutput].outputDataSource = self;
[[EZOutput sharedOutput] startPlayback];
Anyone has any idea about this issue please? Have I missed something?
Thanks for your help!
You should set the category to AVAudioSessionCategoryPlayback. When you have it set to AVAudioSessionCategoryPlayAndRecord, the bluetooth device needs to be available for input as well as output. If it is not, the device will default to internal speakers for playback.

AVSpeechSynthesizer won't work when phone locked

I am trying to use AVSpeechSynthesizer when the phone is locked, but the audio stops when I lock the screen. I am using the simulator, not an actual device. I have seen a couple other questions similar to this on this site and I followed their recommendations, but it still does not work.
In the app delegate I set the audio session category to AVAudioSessionCategoryPlayback.
- (void)configureAudioSession{
NSError *error = NULL;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
if(error) {
NSLog(#"Error setting category of audio session: %#",error.description);
}
error = NULL;
[[AVAudioSession sharedInstance] setActive:YES error: &error];
if (error) {
NSLog(#"Error activating audio session: %#",error.description);
}
}
And I checked the 'Audio and Airplay' mode under Project Settings->Capabilities->Background Modes.
Can anyone tell me how to get this to work?
Here's how I got AVSpeechSynthesizer to continue speaking when phone goes idle, if phone gets locked, or if app goes to background. (iOS8)
Step 1) Open up info.plist and add the key "Required background modes". Within this array, add a String called "App plays audio or streams audio/video using AirPlay".
Step 2) Add the following to your app delegate didFinishLaunchingWithOptions:
NSError *error = NULL;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:&error];
if(error) {
// Do some error handling
}
[session setActive:YES error:&error];
if (error) {
// Do some error handling
}
Step 3) Run on your device and test it out!
I was able to follow this post to get it to work about a month ago:
AVAudioPlayer stops playing on screen lock even though the category is AVAudioSessionCategoryPlayback
Basically, you need to make entry in your app's .plist file. I'm not sure this will work on the simulator, so you will probably want to test it on an actual device.

How Do I Route Audio to Speaker without using AudioSessionSetProperty?

As AudioSessionSetProperty may become deprecated, I'm trying to find an code example of how to route audio to the speaker using other means.
Previously I did the following:
-(void)setSpeakerEnabled
{
debugLog(#"%s",__FUNCTION__);
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (
kAudioSessionProperty_OverrideAudioRoute,
sizeof (audioRouteOverride),
&audioRouteOverride
);
}
Trying to get same result but without call to AudioSessionSetProperty.
On each release of iOS, more of the audioSession properties are migrated to AVFoundation, so you should use those in preference whenever available.
Since iOS 6 kAudioSessionProperty_OverrideAudioRoute is represented in AVAudioSession by the method
- (BOOL)overrideOutputAudioPort:error:
Available values are AVAudioSessionPortOverrideNone and AVAudioSessionPortOverrideSpeaker
Here is an example audio session configured entirely via AVFoundation:
- (void)configureAVAudioSession
{
// Get your app's audioSession singleton object
AVAudioSession *session = [AVAudioSession sharedInstance];
// Error handling
BOOL success;
NSError *error;
// set the audioSession category.
// Needs to be Record or PlayAndRecord to use audioRouteOverride:
success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
error:&error];
if (!success) {
NSLog(#"AVAudioSession error setting category:%#",error);
}
// Set the audioSession override
success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:&error];
if (!success) {
NSLog(#"AVAudioSession error overrideOutputAudioPort:%#",error);
}
// Activate the audio session
success = [session setActive:YES error:&error];
if (!success) {
NSLog(#"AVAudioSession error activating: %#",error);
}
else {
NSLog(#"AudioSession active");
}
}
UPDATE
Since iOS 7.0, the Audio Session Services C API is now fully deprecated in favour of AVAudioSession.
UPDATE 2
- (BOOL)overrideOutputAudioPort:error:
is a method, not a property, and it sets an underlying write-only UInt32 value. You can't get the current value, and you should treat the method as setting a temporary state. If the audio route changes or is interrupted, the property resets to its default (AVAudioSessionPortOverrideNone). You can get interruption notifications via AVAudioSessionDelegate.
NSError *error;
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:&error];
if(error)
{
NSLog(#"Error: AudioSession cannot use speakers");
}
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .spokenAudio, options: .defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print("error.")
}
// paste this code in your viewLoad region
Foundry’s solution together with this blog by Mario Diana has also allowed me to upgrade audio session set up code deprecated in iOS 7. My old code was based on
AudioBufferPlayer by Matthijs Hollemans.
Remember to add the AVFoundation.framework.

Resources