iOS 9如何检测静音模式?

时间:2022-04-01 00:20:01

As AudioSessionInitialize and AudioSessionGetProperty are deprecated, I am getting the wrong return values:

由于不推荐使用AudioSessionInitialize和AudioSessionGetProperty,我收到错误的返回值:

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;

From this code (I found it here), I get the same incorrect result no matter what state is actually device on. How can I detect if the silent mode is ON on device right now?

从这段代码(我在这里找到),无论实际设备处于何种状态,我都会得到相同的错误结果。如何检测设备上的静音模式是否为ON?

1 个解决方案

#1


6  

The API is no longer available. But the work around is simple:

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

  • Play a short audio and detect time that it finishes playing
  • 播放短音频并检测完成播放的时间

  • If the time that it finishes playing is shorter than the actual length of the audio, than the device is muted
  • 如果完成播放的时间短于音频的实际长度,则设备静音

Hoishing posted a helper class MuteChecker on his blog. Use it as the following:

Hoishing在他的博客上发布了一个帮助类MuteChecker。使用它如下:

self.muteChecker = [[MuteChecker alloc] initWithCompletionBlk:^(NSTimeInterval lapse, BOOL muted) {
    NSLog(@"muted: %d", muted);
}];
[self.muteChecker check];

This is the complete code for the class, you can simple copy past to your project:

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

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

Important note: you will also have to provide a short audio MuteChecker.caf for the code to work. You could download one from his blog directly or generate one yourself.

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

#1


6  

The API is no longer available. But the work around is simple:

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

  • Play a short audio and detect time that it finishes playing
  • 播放短音频并检测完成播放的时间

  • If the time that it finishes playing is shorter than the actual length of the audio, than the device is muted
  • 如果完成播放的时间短于音频的实际长度,则设备静音

Hoishing posted a helper class MuteChecker on his blog. Use it as the following:

Hoishing在他的博客上发布了一个帮助类MuteChecker。使用它如下:

self.muteChecker = [[MuteChecker alloc] initWithCompletionBlk:^(NSTimeInterval lapse, BOOL muted) {
    NSLog(@"muted: %d", muted);
}];
[self.muteChecker check];

This is the complete code for the class, you can simple copy past to your project:

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

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

Important note: you will also have to provide a short audio MuteChecker.caf for the code to work. You could download one from his blog directly or generate one yourself.

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