Как программно воспринимать переключатель отключения звука iPhone?

Я не могу найти в SDK, как программно ощущать кнопку/кнопку отключения звука на iPhone. Когда мое приложение играет в фоновой музыке, оно правильно реагирует на кнопку громкости, без меня не будет никакого кода, который следует за этим, но когда я использую переключатель отключения звука, он просто продолжает проигрывать.

Как проверить положение отключения звука?

(ПРИМЕЧАНИЕ. Моя программа имеет свой собственный переключатель отключения звука, но я бы хотел, чтобы физический переключатель переопределил это.)

Спасибо!

Ответ 1

Спасибо, JPM. Действительно, ссылка, которую вы предоставляете, приводит к правильному ответу (в конце концов.;) Для полноты (потому что S.O. должен быть источником БЫСТРОГО ответа!)...

// "Ambient" makes it respect the mute switch
// Must call this once to init session
if (!gAudioSessionInited)
{
    AudioSessionInterruptionListener    inInterruptionListener = NULL;
    OSStatus    error;
    if ((error = AudioSessionInitialize (NULL, NULL, inInterruptionListener, NULL)))
    {
        NSLog(@"*** Error *** error in AudioSessionInitialize: %d.", error);
    }
    else
    {
        gAudioSessionInited = YES;
    }
}

SInt32  ambient = kAudioSessionCategory_AmbientSound;
if (AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (ambient), &ambient))
{
    NSLog(@"*** Error *** could not set Session property to ambient.");
}

Ответ 2

Я ответил на аналогичный вопрос здесь (ссылка). Соответствующий код:

 -(BOOL)silenced {
     #if TARGET_IPHONE_SIMULATOR
         // return NO in simulator. Code causes crashes for some reason.
         return NO;
     #endif

    CFStringRef state;
    UInt32 propertySize = sizeof(CFStringRef);
    AudioSessionInitialize(NULL, NULL, NULL, NULL);
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
    if(CFStringGetLength(state) > 0)
            return NO;
    else
            return YES;

    }

Ответ 3

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

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

-(BOOL)muteSwitchEnabled {

#if TARGET_IPHONE_SIMULATOR
    // set to NO in simulator. Code causes crashes for some reason.
    return NO;
#endif

// go back to Ambient to detect the switch
AVAudioSession* sharedSession = [AVAudioSession sharedInstance];
[sharedSession setCategory:AVAudioSessionCategoryAmbient error:nil];

CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);

BOOL muteSwitch = (CFStringGetLength(state) <= 0);
NSLog(@"Mute switch: %d",muteSwitch);

// code below here is just restoring my own audio state, YMMV
_hasMicrophone = [sharedSession inputIsAvailable];
NSError* setCategoryError = nil;

if (_hasMicrophone) {

    [sharedSession setCategory: AVAudioSessionCategoryPlayAndRecord error: &setCategoryError];

    // By default PlayAndRecord plays out over the internal speaker.  We want the external speakers, thanks.
    UInt32 ASRoute = kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                             sizeof (ASRoute),
                             &ASRoute
                             );
}
else
    // Devices with no mike don't support PlayAndRecord - we don't get playback, so use just playback as we don't have a microphone anyway
    [sharedSession setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];

if (setCategoryError)
    NSLog(@"Error setting audio category! %@", setCategoryError);

return muteSwitch;
}

Ответ 4

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

-(NSString*)audioRoute
{
    CFStringRef state;
    UInt32 propertySize = sizeof(CFStringRef);
    OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
    if( n )
    {
        // TODO: Throw an exception
        NSLog( @"AudioSessionGetProperty: %@", osString( n ) );
    }

    NSString *result = (NSString*)state;
    [result autorelease];
    return result;
}

-(Float32)audioVolume
{
    Float32 state;
    UInt32 propertySize = sizeof(CFStringRef);
    OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputVolume, &propertySize, &state);
    if( n )
    {
        // TODO: Throw an exception
        NSLog( @"AudioSessionGetProperty: %@", osString( n ) );
    }
    return state;
}

Ответ 5

-(BOOL)isDeviceMuted
{
 CFStringRef state;
 UInt32 propertySize = sizeof(CFStringRef);
 AudioSessionInitialize(NULL, NULL, NULL, NULL);
 AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
 return (CFStringGetLength(state) > 0 ? NO : YES);
}

Ответ 6

Olie,

Я считаю, что вы можете найти ответ на свой вопрос здесь:

https://devforums.apple.com/message/1135#1135

Я предполагаю, что у вас есть доступ к форумам разработчиков на Apple.com:)

Ответ 7

Я следовал общей теории здесь и получил это, чтобы работать http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/

Вот краткое описание: воспроизведите короткий тихий звук. Время, необходимое для игры. Если переключатель отключения звука включен, воспроизведение звука вернется намного короче, чем сам звук. Я использовал звук 500 мс, и если звук воспроизводился меньше, чем в этот раз, тогда включается переключатель отключения звука. Я использую Audio Services для воспроизведения тихого звука (который всегда отличает переключатель отключения звука). В этой статье говорится, что вы можете использовать AVAudioPlayer для воспроизведения этого звука. Если вы используете AVAudioPlayer, я предполагаю, что вам нужно настроить свою категорию AVAudioSession, чтобы почитать переключатель отключения звука, но я не пробовал его.

Ответ 8

Использование режима Ambient для воспроизведения видео и режима PlayAndRecord для записи видео на экране камеры разрешает проблему в нашем случае.

Код в приложении: didFinishLaunchingWithOptions:

NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];

Код в viewWillAppear на cameraController, если вам нужно использовать камеру или запись в своем приложении

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

Код в viewWillDisappear на cameraController

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];

Используя эти строки, наши приложения записывают и воспроизводят видео и отключенный звук, отлично работает под iOS8 и iOS7.

Ответ 9

Для Свифта

Ниже рамки отлично работает в устройстве

https://github.com/akramhussein/Mute

Просто установите используя pod или скачайте с Git

pod 'Mute'

и используйте как ниже код

import UIKit
import Mute

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel! {
        didSet {
            self.label.text = ""
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Notify every 2 seconds
        Mute.shared.checkInterval = 2.0

        // Always notify on interval
        Mute.shared.alwaysNotify = true

        // Update label when notification received
        Mute.shared.notify = { m in
            self.label.text = m ? "Muted" : "Not Muted"
        }

        // Stop after 5 seconds
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            Mute.shared.isPaused = true
        }

        // Re-start after 10 seconds
        DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
            Mute.shared.isPaused = false
        }
    }

}