可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I can\'t seem to find in the SDK how to programatically sense the mute button/switch on the iPhone. When my app plays background music, it responds properly to the volume button without me having any code to follow that but, when I use the mute switch, it just keeps playing away.
How do I test the position of mute?
(NOTE: My program has its own mute switch, but I\'d like the physical switch to override that.)
Thanks!
回答1:
Thanks, JPM. Indeed, the link you provide leads to the correct answer (eventually. ;) For completeness (because S.O. should be a source of QUICK answers! )...
// \"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:
I answered a similar question here (link). The relevant code:
-(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:
Some of the code in other answers (including the accepted answer) may not work if you aren\'t in the ambient mode, where the mute switch is respected.
I wrote the routine below to switch to ambient, read the switch, and then return to the settings I need in my app.
-(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:
To find out the state of the mute switch and the volume control I wrote these two functions. These are ideal if you wish to warn the user before they try creating audio output.
-(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,
I believe you can find the answer to your question here:
https://devforums.apple.com/message/1135#1135
I\'m assuming you have access to the Developer Forums at Apple.com :)
回答7:
I followed the general theory here and got this to work
http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/
Here is a recap: Play a short silent sound. Time how long it takes to play. If the mute switch is on, the playing of the sound will come back much shorter than the sound itself. I used a 500ms sound and if the sound played in less than this time, then the mute switch was on. I use Audio Services to play the silent sound (which always honors the mute switch). This article says that you can use AVAudioPlayer to play this sound. If you use AVAudioPlayer, I assume you\'ll need to setup your AVAudioSession\'s category to honor the mute switch, but I have not tried it`.
回答8:
Using Ambient mode for playing a video and PlayAndRecord mode for recording a video on camera screen, resolves the issue in our case.
The code in application:didFinishLaunchingWithOptions:
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
The code in viewWillAppear on cameraController, if you have to use camera or recording in your app
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
The code in viewWillDisappear on cameraController
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
Using these lines our Application records and plays a video and mute switch works perfectly under both iOS8 and iOS7!!!
回答9:
For Swift
Below framework works perfectly in device
https://github.com/akramhussein/Mute
Just install using pod or download from Git
pod \'Mute\'
and use like below code
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
}
}
}
回答10:
Here two examples how to use AudioSessionInitialize:
http://www.restoroot.com/Blog/2008/12/25/audiosessioninitialize-workarounds/