Обнаружено, что не работает переключатель iPhone Ring / Silent / Mute с помощью AVAudioPlayer?
Я попытался использовать эти методы, чтобы определить, активен ли переключатель "Звонок / Без звука":
Как программно определить выключатель звука iPhone?
Категория AVAudioSession не работает, как того требует документация
Но на моем iPhone 4 значением "state" всегда является "Speaker" (а значение длины, возвращаемое CFStringGetLength(state), всегда равно 7). Кто-нибудь успешно использовал этот метод? Если да, то на каком устройстве и версии SDK?
Я называю это так:
- (BOOL)deviceIsSilenced {
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
OSStatus audioStatus = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
if (audioStatus == kAudioSessionNoError) {
NSLog(@"audio route: %@", state) // "Speaker" regardless of silent switch setting, but "Headphone" when my headphones are plugged in
return (CFStringGetLength(state) <= 0);
}
return NO;
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
audioSession.delegate = self;
[audioSession setCategory:AVAudioSessionCategoryAmbient error:nil];
[audioSession setActive:YES error:nil];
NSLog(@"muted? %i", [self deviceIsSilenced]);
...
}
Я подумал, может быть, какое-то другое (более точное) событие kAudioSessionProperty происходит, когда физический коммутатор на телефоне... переключается. У кого-нибудь есть идеи?
Кстати, я использую категорию AVAudioSessionCategoryAmbient с моим [AVAudioSession sharedInstance].
Обновление: я также попытался использовать различные аудио категории и несколько других свойств аудио сеанса, ни одно из которых не срабатывает при выключении / выключении звука.:(
Обновление от 1 января 2014 года: Это что-то вроде хака, и я столкнулся со сбоем во время многозадачности на своем iPhone 5S, но библиотека SoundSwitch, связанная с новым принятым ответом, - это путь, если вы хотите обнаружить бесшумный выключатель. Это даже работает в iOS 7.
7 ответов
Я прошел через эту библиотеку VSSilentSwitch.
Не работает для меня (не работает, когда вы на самом деле начинаете использовать аудио).
Я думал о том, как он это сделал, а потом понял, что звонок завершения аудио вызывается почти сразу, как только начинает звучать звук, когда мы молчим.
Чтобы быть более конкретным:
Системные звуки воспроизводятся с использованием AudioServicesPlaySystemSound
завершит воспроизведение, как только оно начнется.
Конечно, это будет работать только с аудио категориями, которые поддерживают тихий переключатель (по умолчанию AVAudioSessionCategoryAmbient
уважает это).
Таким образом, задача состоит в том, чтобы создать системный звук, предпочтительно тихий звук, и продолжать воспроизводить его снова и снова, проверяя время, которое потребовалось от воспроизведения до завершения (установите процедуру завершения, используя AudioServicesAddSystemSoundCompletion
).
Если процедура завершения вызывается очень скоро (разрешить некоторый порог) - это означает, что тихий переключатель включен.
У этого трюка есть много предостережений, самым большим из которых является то, что он не будет работать на всех аудио категориях.
Если ваше приложение воспроизводит звук в фоновом режиме - убедитесь, что вы остановили этот тест в фоновом режиме, иначе ваше приложение будет работать вечно в фоновом режиме (и будет также отклонено яблоком).
Ну, я нашел ответ благодаря кому-то из форумов разработчиков, и вам это не понравится!
Я получил ответ от Apple на это.
Они сказали, что не предоставляют и никогда не предлагали метод обнаружения аппаратного отключения звука, и не намерены это делать.
:(
IMO, безусловно, имеет смысл обнаруживать тихий переключатель и уведомлять пользователя, если он забыл, что он был включен... У меня были люди, которые жаловались, что у них нет звука, и причиной был тихий переключатель! Ну что ж.
PS: Если вы хотите, чтобы Apple добавила эту функцию (и, конечно, вы это делаете!), Пожалуйста, отправьте новый отчет об ошибке "Улучшение" для "iPhone SDK" по адресу http://bugreport.apple.com/
Обновление: хотя до сих пор нет официального способа проверить состояние переключателя отключения звука, есть обходной путь / библиотека под названием "SoundSwitch", которая, кажется, делает свое дело. Проверьте новый принятый ответ по ссылке.
"Однако, если кто-то может показать нам, как использовать эту AudioSessionProperty_AudioRouteDescription, щедрость по праву принадлежит ему".
Ну, просто NSLog() результат, и вы получите
routes: {
"RouteDetailedDescription_Inputs" = (
);
"RouteDetailedDescription_Outputs" = (
{
"RouteDetailedDescription_PortType" = Speaker;
}
);
}
К сожалению, я получаю такой же результат на iPad2/OS 5.0 как приглушенный, так и без звука. Таким образом, он выглядит функционально эквивалентным kAudioSessionProperty_AudioRoute, никакой радости нет.
Глядя на доски разработчиков, вы обнаружите, что это часто встречающаяся проблема, лучше всего
"Я сообщил об этой проблеме с rdar://9781189 еще в июле, и проблема все еще присутствует в GM".
Так что да... конечно, похоже, что вы SOL с этим в 5.0.
ДОПОЛНЕНИЕ:
"Но как насчет того CFDictionary, который вы регистрируете. Как я могу получить доступ к ключу"RouteDetailedDescription_PortType"?"
Бесплатный звонок - ваш друг.
CFDictionaryRef asCFType = nil;
UInt32 dataSize = sizeof(asCFType);
AudioSessionGetProperty(kAudioSessionProperty_AudioRouteDescription, &dataSize, &asCFType);
NSDictionary *easyPeasy = (NSDictionary *)asCFType;
NSDictionary *firstOutput = (NSDictionary *)[[easyPeasy valueForKey:@"RouteDetailedDescription_Outputs"] objectAtIndex:0];
NSString *portType = (NSString *)[firstOutput valueForKey:@"RouteDetailedDescription_PortType"];
NSLog(@"first output port type is: %@!", portType);
производит
Первый тип выходного порта: Динамик!
Многие распространенные типы CFT связаны с более удобными типами.
Теперь требуется немного практики, чтобы правильно угадать, какие магические заклинания получат что-то полезное из словаря, как указано выше. Помощник по дампам классов по этим направлениям поможет вам освоиться с этим:
- (void)whatsInThis:(CFDictionaryRef)thingy
{
NSDictionary *dict = (NSDictionary *)thingy;
for (NSString *key in dict.allKeys)
{
id value = [dict valueForKey:key];
NSLog(@"key: %@ value type %@", key, [value class]);
if ([value isKindOfClass:[NSArray class]])
{
NSArray *array = (NSArray *)value;
for (id item in array)
{
NSLog(@" -- object type %@", [item class]);
if ([item isKindOfClass:[NSDictionary class]])
[self whatsInThis:item];
}
}
}
}
который для нашего словаря под рукой производит (добавляя отступ для ясности)
key: RouteDetailedDescription_Inputs value type __NSCFArray
key: RouteDetailedDescription_Outputs value type __NSCFArray
-- object type __NSCFDictionary
key: RouteDetailedDescription_PortType value type __NSCFString
что позволяет вам точно знать, что вы могли бы вывести из исходного журнала, зная, что NSLog отображает массивы в () и словари в { }, так что правильное приведение было в высшей степени угаданным. Но некоторые структуры CFType труднее разобрать, чем это.
Хорошо, после kAudioSessionProperty_AudioRoute
используя CMD + клик, я нашел это:(
/*!
@enum AudioSession audio categories states
@abstract Deprecated AudioSession properties
@constant kAudioSessionProperty_AudioRoute
Deprecated in iOS 5.0; Use kAudioSessionProperty_AudioRouteDescription
*/
enum {
kAudioSessionProperty_AudioRoute = 'rout', // CFStringRef (get only)
};
Оказывается, мы должны использовать kAudioSessionProperty_AudioRouteDescription
, но этот парень возвращает CFDictionaryRef
или что-то, и я понятия не имею, как с этим бороться....
Я сделал это ответом в случае, если никто не показывает нам, как использовать kAudioSessionProperty_AudioRouteDescription
где я постараюсь принять мой ответ...
Тем не менее, если кто-то может показать нам, как использовать это kAudioSessionProperty_AudioRouteDescription
Щедрость по праву принадлежит ему.
редактировать:
Понятно, что это проблема iOS 5. Я не говорил об этом раньше, потому что это выглядело слишком очевидно, но потом я подумал, что это может быть не так очевидно для поисковых систем... если вы понимаете, что я имею в виду.
Таким образом, iOS 5 не работает с переключателем "Без звука" / "Отключение звука" на iPhone из-за указанного устаревшего значения.
Попробуйте вставить эту строку над вызовом AudioSessionGetProperty внутри deviceIsSilenced
AudioSessionInitialize (NULL, NULL, NULL, NULL);
Затем должен начать возвращать пустую строку, когда переключатель выключен (хотя покажет наушники и некоторые другие состояния, если BT гарнитура или аксессуар подключены, например).
Я не верю, что в общедоступном API есть что-то, что сработает при перемещении фактического переключателя.
Нашел эту библиотеку http://www.verietassoftware.com/index.php?option=com_content&view=article&id=27&Itemid=115
Разрешит ли Apple такое? Это библиотека размером 500 Кбайт, выполняющая черную магию с настройками звука и телефона.
Я думаю, у вас неправильное впечатление. Маршрут - это то, куда он идет. Вы хотите знать уровень громкости. использование kAudioSessionProperty_CurrentHardwareOutputVolume