Ответ 1
Сначала вам нужно настроить сеанс аудиозаписей приложений, чтобы разрешить соединения Bluetooth, поддерживающие аудио. Вы можете сделать это, например, в приложении приложения-приложения (BOOL): (UIApplication *) application doneFinishLaunchingWithOptions: (NSDictionary *) метод запускаОпции. Убедитесь, что вы привязываете структуру AVFoundation и импортируете ее в заголовки, которые будут использовать ее.
#import <AVFoundation/AVFoundation.h>// place in .h
[self prepareAudioSession];// called from application didFinishLaunchingWithOptions
- (BOOL)prepareAudioSession {
// deactivate session
BOOL success = [[AVAudioSession sharedInstance] setActive:NO error: nil];
if (!success) {
NSLog(@"deactivationError");
}
// set audio session category AVAudioSessionCategoryPlayAndRecord options AVAudioSessionCategoryOptionAllowBluetooth
success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
if (!success) {
NSLog(@"setCategoryError");
}
// activate audio session
success = [[AVAudioSession sharedInstance] setActive:YES error: nil];
if (!success) {
NSLog(@"activationError");
}
return success;
}
У каждого приложения есть одноэлементный аудио-сеанс, который вы можете настроить. Категория и режим сеансов (в этом примере я не установил режим, чтобы он возвращался к режиму по умолчанию) объявлял ваши приложения о том, как вы хотите обработать аудиомаршрутизацию. Это следует за важным правилом last in wins. Это означает, что если пользователь подключается к гарнитуре или в этом случае устройство Bluetooth, которое является периферийным устройством (HFP), система автоматически направит звук на гарнитуру или устройство Bluetooth. Физические действия пользователей используются для определения маршрутизации звука. Однако, если вы хотите предоставить пользователю список доступных маршрутов, Apple рекомендует использовать класс MPVolumeView.
Пример добавления MPVolumeView может быть помещен в метод UIViewController viewDidLoad подкласса.
#import <MediaPlayer/MediaPlayer.h> // place in .h
// prefered way using MPVolumeView for user selecting audio routes
self.view.backgroundColor = [UIColor clearColor];
CGRect frameForMPVV = CGRectMake(50.0, 50.0, 100.0, 100.0);
MPVolumeView *routeView = [[MPVolumeView alloc] initWithFrame:frameForMPVV];
[routeView setShowsVolumeSlider:NO];
[routeView setShowsRouteButton:YES];
[self.view addSubview: routeView];
Как и в iOS 7, вы можете получить все входы вроде этого
// portDesc.portType could be for example - BluetoothHFP, MicrophoneBuiltIn, MicrophoneWired
NSArray *availInputs = [[AVAudioSession sharedInstance] availableInputs];
int count = [availInputs count];
for (int k = 0; k < count; k++) {
AVAudioSessionPortDescription *portDesc = [availInputs objectAtIndex:k];
NSLog(@"input%i port type %@", k+1, portDesc.portType);
NSLog(@"input%i port name %@", k+1, portDesc.portName);
}
ПортType, который вас интересует, это "BluetoothHFP". Свойством portName обычно является производитель/модель, которую вы показываете пользователю. (Я проверил это с динозавром Motorola, отличным от LE, и он работает)
Из-за правила last in wins вам понадобятся следующие два уведомления (включая iOS 7). Один для обработки прерываний (таких как телефонные звонки или будильник), а второй для уведомления об изменениях маршрута. Уведомления об изменении маршрута относятся к этому вопросу.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(myInterruptionSelector:)
name:AVAudioSessionInterruptionNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(myRouteChangeSelector:)
name:AVAudioSessionRouteChangeNotification
object:nil];
Для iOS 6.x вы можете прочитать свойство currentRoute для AVAudioSession внутри селектора myRouteChange: для получения нового маршрута, так как это будет вызвано при подключении гарнитуры или Bluetooth-устройства.
- (void)myRouteChangeSelector:(NSNotification*)notification {
AVAudioSessionRouteDescription *currentRoute = [[AVAudioSession sharedInstance] currentRoute];
NSArray *inputsForRoute = currentRoute.inputs;
NSArray *outputsForRoute = currentRoute.outputs;
AVAudioSessionPortDescription *outPortDesc = [outputsForRoute objectAtIndex:0];
NSLog(@"current outport type %@", outPortDesc.portType);
AVAudioSessionPortDescription *inPortDesc = [inputsForRoute objectAtIndex:0];
NSLog(@"current inPort type %@", inPortDesc.portType);
}
Любая версия iOS < 6.0 вам понадобится класс "теперь устаревший" AudioSessionServices. Этот класс является C api, который вместо уведомлений позволяет добавлять слушателей свойств.
Я закончу эту заметку - ВЫ НЕ ДОЛЖНЫ ВСЕГДА ПОЛУЧИТЬ ЧТО ВЫ ХОТИТЕ ИЗ СИСТЕМЫ. Уведомления об обработке прерываний необходимо соблюдать, и требуется большая проверка ошибок. Я думаю, что это действительно хороший вопрос, и я надеюсь, что это проливает свет на то, что вы пытаетесь достичь.