Обнаружено, что не работает переключатель iPhone Ring / Silent / Mute с помощью AVAudioPlayer? - PullRequest
31 голосов
/ 01 августа 2011

Я пытался использовать эти методы, пытаясь определить, активен ли переключатель «Звонок / Без звука»:

Как программно определить выключатель звука 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 ]

29 голосов
/ 04 ноября 2011

Ну, я нашел ответ благодаря кому-то из форумов разработчиков, и вам, ребята, это не понравится!

Я получил ответ от Apple по этому поводу.

Они сказали, что не предоставляют и никогда не предоставляли метод обнаружения аппаратного отключения звука и не намерены это делать.

: (*

ИМО существуетЯ определенно ценю обнаружение тихого переключателя и уведомление пользователя в случае, если он забыл, что он был включен ... У меня были люди, жалующиеся на то, что у них нет звука, и причиной был тихий переключатель! О, хорошо.

PS: Если вы хотите, чтобы Apple добавила эту функцию (и, конечно, вы это делаете!), Отправьте новый отчет об ошибке «Улучшение» для «iPhone SDK» на http://bugreport.apple.com/

Обновление: Хотя до сих пор нет официального способа проверить состояние переключателя отключения звука, есть обходной путь / библиотека под названием "SoundSwitch", которая, кажется, делает свое дело. Проверьте новый принятый ответ дляссылка.

11 голосов
/ 20 октября 2011

"Однако, если кто-то может показать нам, как использовать эту AudioSessionProperty_AudioRouteDescription, щедрость по праву принадлежит ему."

Ну, просто NSLog () результат, и вы получите

routes: {
    "RouteDetailedDescription_Inputs" =     (
    );
    "RouteDetailedDescription_Outputs" =     (
                {
            "RouteDetailedDescription_PortType" = Speaker;
        }
    );
}

К сожалению, я получаю такой же результат на iPad2 / OS 5.0, как приглушенный, так и без звука.Похоже, что он функционально эквивалентен kAudioSessionProperty_AudioRoute, радости нет.

Глядя на доски разработчика, обнаруживаю, что это часто встречающаяся проблема, лучше всего описанная с помощью

"Я сообщил об этой проблеме сrdar: // 9781189 в июле, и проблема все еще присутствует в GM. "

Так что да ... конечно, похоже, что вы SOL с этим в 5.0.

ADDENDUM:

"Но как насчет того 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!

Многие распространенные типы CFT соединены с более удобными типами.

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 труднее разобрать, чем это.

3 голосов
/ 02 июня 2013

Я прошел эту библиотеку VSSilentSwitch.
Не работает для меня (не работает, когда вы фактически начинаете использовать аудио).
Я думал о том, как он это сделал, а потом понял, что звонок о завершении звука вызывается почти сразу, как только начинает звучать звук, когда мы молчим.
Чтобы быть немного более конкретным:
Системные звуки, воспроизводимые с использованием AudioServicesPlaySystemSound, завершат воспроизведение сразу после его запуска.
Конечно, это будет работать только с аудио категориями, которые относятся к переключателю тишины (по умолчанию AVAudioSessionCategoryAmbient учитывает это).
Таким образом, хитрость заключается в том, чтобы создать системный звук, предпочтительно тихий звук, и продолжать воспроизводить его снова и снова, проверяя время, которое потребовалось от воспроизведения до завершения (установите процедуру завершения, используя AudioServicesAddSystemSoundCompletion).
Если процедура завершения вызывается очень скоро (разрешить некоторый порог) - это означает, что тихий переключатель включен.
У этого трюка есть много предостережений, самым большим из которых является то, что он не будет работать на всех аудио категориях.
Если ваше приложение воспроизводит звук в фоновом режиме - обязательно остановите этот тест в фоновом режиме, иначе ваше приложение будет работать вечно в фоновом режиме (и будет также отклонено яблоком).

0 голосов
/ 18 марта 2012

Нашел эту библиотеку http://www.verietassoftware.com/index.php?option=com_content&view=article&id=27&Itemid=115

Разрешит ли Apple такое? Это библиотека размером 500 КБ, выполняющая черную магию с настройками звука и телефона

0 голосов
/ 20 октября 2011

Я думаю, у вас неправильное впечатление. Маршрут - это то, куда он идет. Вы хотите знать уровень громкости. Используйте kAudioSessionProperty_CurrentHardwareOutputVolume

0 голосов
/ 16 октября 2011

ОК, после 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 не работает с переключателем тишины / отключения звука на iPhone из-за указанного устаревшего значения.

0 голосов
/ 02 августа 2011

Попробуйте вставить эту строку над вызовом AudioSessionGetProperty внутри deviceIsSilenced

AudioSessionInitialize (NULL, NULL, NULL, NULL);

Должен ли тогда начаться возврат пустой строки, когда переключатель выключен (хотя будетпокажите наушники и некоторые другие состояния, если BT-гарнитура или аксессуар подключены, например).

FWIW Я не верю, что в общедоступном API есть что-то, что сработает при перемещении фактического переключателя.

...