On iOS devices, there are mainly two types of sounds:
- Ringtones and reminders: Including system sounds such as phone calls, text messages, notifications (also including key tones, lock sounds, which can be set in the settings to enable or disable), they are controlled by the physical mute switch key, that is, when When the device is muted, these sounds will not be played.
- Media sound: Generally it is the sound when the App is playing audio and video. The volume can be controlled by the physical volume +/- key, not by the device's mute switch key. When the mute key is turned on, we can still use the related API as normal Play sound.
Therefore, the mute here is related to two situations, a) “turn on mute through the physical mute button” and b) “turn down the media volume to 0”. The latter one is fairly simple, we can use [AVAudioSession sharedInstance].outputVolume
to obtain whether the current volume is 0 to determine.
Regarding to situation a, we have a simple solution before iOS 5:
- (BOOL)isMuted {
CFStringRef route;
UInt32 routeSize = sizeof(CFStringRef);
OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &routeSize, &route);
if (status == kAudioSessionNoError) {
if (route == NULL || !CFStringGetLength(route))
return YES;
}
return NO;
}
However, this method is banned after iOS5, and Apple did not provide relevant new APIs on this. But there is a workaround:
Use the AudioServicesPlaySystemSound
function to play a very short blank audio (assuming 0.2s) and monitor the audio playback completion event. If the interval from the start of play to the callback method called is less than 0.1s, it means that the current mute switch is on.
This is because AudioServicesPlaySystemSound
has a feature: the sound it plays belongs to the system sound effect, so it is controlled by the mute button, and if it is currently in mute mode, the callback of the completion of playback will be executed immediately after calling this function, so the time interval will be small and can be used to determine whether the device is muted. The code is as follows:
static CFTimeInterval startPlayTime;
- (void)monitorMute {
// play start time
startPlayTime = CACurrentMediaTime();
// play a local audio, length is 0.2s: detection.aiff
CFURLRef soundFileURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("detection"), CFSTR("aiff"), NULL);
SystemSoundID soundFileID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundFileID);
AudioServicesAddSystemSoundCompletion(soundFileID, NULL, NULL, PlaySoundCompletionBlock, (__bridge void *)self);
AudioServicesPlaySystemSound(soundFileID);
}
static void PlaySoundCompletionBlock(SystemSoundID SSID, void *clientData) {
AudioServicesRemoveSystemSoundCompletion(SSID);
// play complete
CFTimeInterval playDuring = CACurrentMediaTime() - startPlayTime;
if (playDuring < 0.1) {
NSLog(@"mute");
} else {
NSLog(@"unmute");
}
}