由于不推荐使用AudioSessionInitializeAudioSessionGetProperty,因此我得到了错误的返回值:

CFStringRef state = nil;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
[[AVAudioSession sharedInstance] setActive:YES error:nil];
if (status == kAudioSessionNoError) {
    return CFStringGetLength(state) == 0;   // YES = silent
}
return NO;

从此代码(我发现它为here),无论设备实际处于什么状态,我都会得到相同的错误结果。如何检测当前设备上的静音模式是否为开?

最佳答案

该API不再可用。但是解决方法很简单:

  • 播放简短的音频并检测完成播放
  • 的时间
  • 如果完成播放的时间短于音频的实际长度,则说明设备已静音

  • 霍伊辛(Hoishing)在他的blog上发布了一个助手类MuteChecker。如下使用它:
    self.muteChecker = [[MuteChecker alloc] initWithCompletionBlk:^(NSTimeInterval lapse, BOOL muted) {
        NSLog(@"muted: %d", muted);
    }];
    [self.muteChecker check];
    

    这是该类的完整代码,您可以简单地复制到您的项目中:

    MuteChecker.h
    #import <Foundation/Foundation.h>
    #import <AudioToolbox/AudioToolbox.h>
    
    typedef void (^MuteCheckCompletionHandler)(NSTimeInterval lapse, BOOL muted);
    
    // this class must use with a MuteChecker.caf (a 0.2 sec mute sound) in Bundle
    @interface MuteChecker : NSObject
    -(instancetype)initWithCompletionBlk:(MuteCheckCompletionHandler)completionBlk;
    -(void)check;
    @end
    

    MuteChecker.cpp
    #import "MuteChecker.h"
    
    void MuteCheckCompletionProc(SystemSoundID ssID, void* clientData);
    
    @interface MuteChecker ()
    @property (nonatomic,assign) SystemSoundID soundId;
    @property (strong) MuteCheckCompletionHandler completionBlk;
    @property (nonatomic, strong)NSDate *startTime;
    -(void)completed;
    @end
    
    void MuteCheckCompletionProc(SystemSoundID ssID, void* clientData){
        MuteChecker *obj = (__bridge MuteChecker *)clientData;
        [obj completed];
    }
    
    @implementation MuteChecker
    
    -(void)playMuteSound
    {
        self.startTime = [NSDate date];
        AudioServicesPlaySystemSound(self.soundId);
    }
    
    -(void)completed
    {
        NSDate *now = [NSDate date];
        NSTimeInterval t = [now timeIntervalSinceDate:self.startTime];
        BOOL muted = (t > 0.1)? NO : YES;
        self.completionBlk(t, muted);
    }
    
    -(void)check {
        if (self.startTime == nil) {
            [self playMuteSound];
        } else {
            NSDate *now = [NSDate date];
            NSTimeInterval lastCheck = [now timeIntervalSinceDate:self.startTime];
            if (lastCheck > 1) {    //prevent checking interval shorter then the sound length
                [self playMuteSound];
            }
        }
    }
    
    - (instancetype)initWithCompletionBlk:(MuteCheckCompletionHandler)completionBlk
    {
        self = [self init];
        if (self) {
            NSURL* url = [[NSBundle mainBundle] URLForResource:@"MuteChecker" withExtension:@"caf"];
            if (AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &_soundId) == kAudioServicesNoError){
                AudioServicesAddSystemSoundCompletion(self.soundId, CFRunLoopGetMain(), kCFRunLoopDefaultMode, MuteCheckCompletionProc,(__bridge void *)(self));
                UInt32 yes = 1;
                AudioServicesSetProperty(kAudioServicesPropertyIsUISound, sizeof(_soundId),&_soundId,sizeof(yes), &yes);
                self.completionBlk = completionBlk;
            } else {
                NSLog(@"error setting up Sound ID");
            }
        }
        return self;
    }
    
    - (void)dealloc
    {
        if (self.soundId != -1){
            AudioServicesRemoveSystemSoundCompletion(self.soundId);
            AudioServicesDisposeSystemSoundID(self.soundId);
        }
    }
    
    @end
    

    重要说明:您还必须提供简短的音频MuteChecker.caf才能使代码正常工作。您可以直接从他的博客中下载一个,也可以自己生成一个。

    10-08 06:00