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

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?

解决方案

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

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:

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

#import

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.

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐