Обнаружение переключателя iPhone Ring/Silent/Mute с использованием AVAudioPlayer не работает?
Я попытался использовать эти методы в попытке обнаружить, что переключатель Ring/Silent активен или нет:
Как программно определить переключатель отключения звука iPhone?
Категория AVAudioSession не работает в соответствии с документацией
Но на моем iPhone 4 значение "state" всегда "Speaker" (и значение длины, возвращаемое CFStringGetLength (состояние), всегда равно 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.
Ответы
Ответ 1
Я прошел через эту библиотеку VSSilentSwitch.
Не работал у меня (не работает, когда вы начинаете использовать аудио).
Я думал о том, как он это сделал, а затем понял, что вызов завершения звука называется почти сразу после начала звучания звука, когда мы молчим.
Чтобы быть более конкретным:
Звуки системы, воспроизводимые с использованием AudioServicesPlaySystemSound
, завершат воспроизведение сразу же после его запуска.
Конечно, это будет работать только с аудио категориями, которые относятся к тихим переключателям (по умолчанию это соответствует AVAudioSessionCategoryAmbient
).
Итак, фокус в том, чтобы создать системный звук, желательно тихий звук, и продолжать воспроизводить его снова и снова, проверяя время, которое требуется от воспроизведения до завершения (установите процедуру завершения с помощью AudioServicesAddSystemSoundCompletion
).
Если завершение proc вызывается очень скоро (допустим некоторый порог) - это означает, что включен тихий переключатель.
Этот трюк имеет много предостережений, самый большой из которых заключается в том, что он не будет работать во всех категориях аудио.
Если ваше приложение воспроизводит аудио в фоновом режиме - убедитесь, что вы остановили этот тест в фоновом режиме, или ваше приложение будет работать навсегда в фоновом режиме (и также будет отклонено яблоком).
Ответ 2
Ну, я нашел ответ благодаря кому-то из форумов разработчиков, и вам, ребята, это не понравится!
У меня был ответ от Apple.
Они сказали, что они этого не делают и никогда не предоставляли метод обнаружения аппаратного отключения звука и не намеревались это делать.
: (
IMO определенно имеет значение для обнаружения молчащего коммутатора и уведомления пользователя, если они забыли, что он был включен... У меня были люди, жалующиеся на то, что у них нет звука, и причиной молчания стал! О, хорошо.
PS: Если вы хотите, чтобы Apple добавила эту функцию (и, конечно же, вы делаете!), пожалуйста, напишите новый отчет об ошибке "Улучшение" для "iPhone SDK" в http://bugreport.apple.com/
Обновление: Пока еще нет официального способа проверить статус переключателя отключения звука, есть обходной путь/библиотека под названием "SoundSwitch", которая, похоже, делает трюк. Ознакомьтесь с новым принятым ответом на ссылку.
Ответ 3
"Однако, если кто-то может показать нам, как использовать эту 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);
производит
Первый тип выходного порта: Speaker!
Многие распространенные типы CFTypes соединяются с более удобными типами.
http://developer.apple.com/library/ios/#documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html
Теперь вам нужно немного практиковаться, чтобы правильно догадаться, какие заклинания магического заклинания получат что-то полезное из словаря, как указано выше. Помощник дампа класса по этим линиям поможет вам ускориться с этим:
- (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 довольно сложны для анализа.
Ответ 4
Попробуйте вставить эту строку над вашим вызовом в AudioSessionGetProperty внутри устройства. IsSilenced
AudioSessionInitialize (NULL, NULL, NULL, NULL);
Затем следует начать возвращать пустую строку, когда переключатель не работает (хотя будет отображаться Headphone и некоторые другие состояния, если BT-гарнитура или аксессуар подключены, например).
FWIW Я не верю, что в публичном API будет что-то, что будет срабатывать при перемещении фактического переключателя.
Ответ 5
Хорошо, после выполнения kAudioSessionProperty_AudioRoute
с помощью CMD + click я нашел следующее: (
/*!
@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 не работает с переключателем silent/mute на iPhone из-за указанного устаревшего значения.
Ответ 6
Я думаю, что вы ошибались. Маршрут - это путь. Вы хотите знать уровень громкости. Используйте kAudioSessionProperty_CurrentHardwareOutputVolume
Ответ 7
Найдено в этой библиотеке
http://www.verietassoftware.com/index.php?option=com_content&view=article&id=27&Itemid=115
Может ли Apple разрешить это? Это библиотека 500Kb, делающая черную магию с настройками звука и телефона.