With the iOS7 the AudioSession Category AVAudioSessionCategoryPlayAndRecord asks for Microphone permission. However, that permission doesn't feel right if I only need to support bluetooth for external audio. There are some people that are in the same situation as I am right now, but I can't find an answer for this.
In iOS6 I was using this code to route the sound to bluetooth devices:
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
error:&sessionError];
AudioSessionSetActive (true);
UInt32 audioCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory,
sizeof (audioCategory), &audioCategory);
Is there any way to support a bluetooth device without using a audio session category that asks the user permission to use the microphone?
PS: I have noticed that google does the same with maps and youtube. Is it possible that we can't get around this issue on iOS7?
The "Allow app to use Microphone" prompt has been put in place to give the user more confidence in what the application is interfacing with. There will be no way to get around this.
You can however respond on the event of the user denying access. This might help:
How to detect microphone input permission refused in iOS 7
Related
We are developing a VOIP application and while there is an active call, we want not to allow other apps play music or something (like Whatsapp does). Is there any way of doing it in a normal way, can you help please?
Edit 1: I think we need to start with listening the observer AVAudioSessionInterruptionNotification.
Accepted Answer Edit 2:
When sound interruption begins, try to only active the AudioSession again. This works. Thank you KudoCC.
Here is a link talks about audio category, there is a table in it:
As your app supports VoIP, so it need to play and record audio, and you need interrupt non-mixable apps audio, so AVAudioSessionCategoryPlayAndRecord is the right category. Also you should re-active your audio session when you're playing/recording audio so that the category takes effect.
Try this code in your app to pause the background audio when calls,
[[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
It is helpful when other apps uses AVAudioPlayer.
For more detail refer this Link
We write app that records audio in background. We use AVAudioSession with AVAudioSessionCategoryPlayAndRecord category and AVAudioSessionCategoryOptionAllowBluetooth option:
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions: AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth error:&error];
We noticed the strange issue - when iPhone connected to Multimedia Car Bluetooth system and our app runs, there are shown phone call from device to itself (the call continues during all device connection to bluetooth system). When we close app - the call is ended, when we open app again - call begins and etc.
This issue reproduces on all Multimedia Bluetooth systems. How can we fix it? Thanks
Think you need to add AVAudioSessionCategoryOptionAllowBluetoothA2DP instead of the old HFP profile. The call is used to make older bluetooth devices to work.
With iOS 10, Apple added the option AVAudioSessionCategoryOptionAllowBluetoothA2DP. They also changed the meaning of AudioSessionCategoryOptionAllowBluetooth to only allow output using the HFP Bluetooth profile, which is where you get the low quality audio output.
If you use this new option in place of the AudioSessionCategoryOptionAllowBluetooth option in your code snippet, it will allow high quality output but disallow low quality audio output.
Here's the online documentation for the options, but unfortunately there's no description for the new iOS 10 options online. You can see more detail in the in-code documentation in AVAudioSession.h
https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions?language=objc
Info from: Keep bluetooth sound when initializing AVAudioSession
I'm trying to combine media playback with VoIP feature (via Twilio) for iOS 9 and 8.While an audio stream plays in the background, I connect or disconnect a Voice Conference session which results in a volume jump from value X to value Y. This jump can be heard, as well as observed by a [AVAudioSession sharedInstance].outputVolume value change.I would like to prevent this jump and keep the volume at a constant level, unless the user manually decides to change it.Further investigation showed that while AVAudioSession's category is set to AVAudioSessionCategoryPlayAndRecord, switching between modes[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeDefault error:&error]and[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVoiceChat error:&error]causes the app to operate in two completely separate volume scales, respectively.i.e there a volume for Mode "Default" and a completely unrelated volume for Mode "Voice Chat".AVAudioSession's documentation seems to omit any mention of volume in relation to mode/category switches and I can't find anything relevant on the interwebs...
Appreciate any help.
When setting your play and record category, pass AVAudioSessionCategoryOptionDefaultToSpeaker as an option:
[[AVAudioSession sharedInstance] AVAudioSessionCategoryPlayAndRecord withOptions: AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
This overrides the default play-and-record behaviour of switching from the speaker to the much quieter receiver. The reason for this being that play-and-record was designed for telephony, where you'd be holding the phone to year ear & presumably wouldn't want to have your hearing damaged by loud sounds.
Megan from Twilio here.
I'm not most familiar with the iOS SDK but you should be able to control connection audio from TCDevice parameters incomingSoundEnabled, outgoingSoundEnabled, and disconnectSoundEnabled as documented here.
Otherwise, I would suggest looking at the sharedInstance properties of AVAudioSession that the Twilio SDK calls upon as demonstrated in this post:
setCategory:error:
setActive:error:
overrideOutputAudioPort:error:
Please let me know if this helps.
I'm using the Novocaine library from: https://github.com/alexbw/novocaine to playback wav files. I know that iOS has its own media player API however its limitation is in the preset equalizers. I need to use Novocaine because I am using NVDSP https://github.com/bartolsthoorn/NVDSP to implement a 10-band graphic equalizer.
Apple rejected my submitted app because it asks for microphone access but it is only a playback app. They said:
"The microphone consent request is generated by the use of either AVAudioSessionCategoryRecord or AVAudioSessionCategoryPlayAndRecord audio categories"
In Novocaine.m, I modified the setupAudio from
UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord
to each of these:
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback
UInt32 sessionCategory = kAudioSessionCategory_AmbientSound
UInt32 sessionCategory = kAudioSessionCategory_SoloAmbientSound
but in each of the above cases, the app still requested microphone access.
I searched all the code and this is the only place where the audio session category is set.
To test, after every modification, you have to do this on the iPod:
Settings -> General -> Reset -> Reset Location & Privacy
otherwise the test is not valid.
I single-stepped through almost all of the Novocaine code with the XCode debugger, but it is very difficult to diagnose, because the microphone access popup only shows when the view is displayed, however, the check for it happens much earlier in the code.
Is there any other place in the code that requests microphone access or which affects microphone access as a side-effect?
I'm using XCode 5.0.2 (5A3005) with iOS SDK 7.0, and my only test device is an iPod Touch 5th generation.
Complete credit goes to DMT4u over at Github for this, but yes, his/her solution worked for me! Comment out the following lines:
UInt32 one = 1;
CheckError( AudioUnitSetProperty(inputUnit,
kAudioOutputUnitPropertyEnableIO,
kAudioUnitScope_Input,
kInputBus,
&one,
sizeof(one)), "Couldn't enable IO on the input scope of output unit");
Source: https://github.com/alexbw/novocaine/issues/76
In my app, if iPhone is connected to Bluetooth headset, play sound with Bluetooth. Else use default speaker.
Here's my code
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVoiceChat error:nil];
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
However, when I tried to use category setCategory:AVAudioSessionCategoryPlayAndRecord. Route to bluetooth device stopped working.. I don't know why. Because by right, the bluetooth option should only work for Record or PlayAndRecord category...
/* only valid with AVAudioSessionCategoryRecord and AVAudioSessionCategoryPlayAndRecord */
Addition: Can I have bluetooth for output ONLY (input still use default Mic from phone)?
UPDATE
I changed the order by calling setMode first, followed by setCategory. It works for the first time running the application (a call). When I tried to do the same action again, currentRoute still gave me output = Bluetooth but the actual output returns to default phone front speaker.
It has been a while since I post this question and I kind forgot what exactly the problem is... If I remembered correctly it's due to another lib that kept rewriting the output route. somehow I fixed it and made it work the way I want.
I contributed the code to Jawbone's AudioSessionManager lib. Hope that helps.