我似乎无法在 SDK 中找到如何以编程方式感知 iPhone 上的静音按钮/开关。当我的应用程序播放背景音乐时,它会正确响应音量按钮,而无需我遵循任何代码,但是,当我使用静音开关时,它只会继续播放。
如何测试静音的位置?
(注意:我的程序有自己的静音开关,但我希望物理开关覆盖它。)
我似乎无法在 SDK 中找到如何以编程方式感知 iPhone 上的静音按钮/开关。当我的应用程序播放背景音乐时,它会正确响应音量按钮,而无需我遵循任何代码,但是,当我使用静音开关时,它只会继续播放。
如何测试静音的位置?
(注意:我的程序有自己的静音开关,但我希望物理开关覆盖它。)
谢谢,摩根大通。实际上,您提供的链接会导致正确答案(最终。;)为了完整性(因为 SO 应该是快速答案的来源!)...
// "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.");
}
我在这里回答了一个类似的问题(链接)。相关代码:
-(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;
}
如果您不在环境模式下,其他答案(包括接受的答案)中的某些代码可能无法工作,在这种模式下静音开关受到尊重。
我编写了下面的例程来切换到环境,读取开关,然后返回到我的应用程序中需要的设置。
-(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;
}
为了找出静音开关和音量控制的状态,我编写了这两个函数。如果您希望在用户尝试创建音频输出之前警告他们,这些是理想的选择。
-(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;
}
-(BOOL)isDeviceMuted
{
CFStringRef state;
UInt32 propertySize = sizeof(CFStringRef);
AudioSessionInitialize(NULL, NULL, NULL, NULL);
AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state);
return (CFStringGetLength(state) > 0 ? NO : YES);
}
我在这里遵循了一般理论并使它起作用 http://inforceapps.wordpress.com/2009/07/08/detect-mute-switch-state-on-iphone/
这里是一个回顾:播放一个简短的无声的声音。时间玩多久。如果静音开关打开,声音的播放将比声音本身短得多。我使用了 500 毫秒的声音,如果声音播放的时间少于这个时间,那么静音开关就打开了。我使用音频服务来播放无声的声音(它总是尊重静音开关)。这篇文章说你可以使用 AVAudioPlayer 来播放这个声音。如果您使用 AVAudioPlayer,我假设您需要设置 AVAudioSession 的类别以支持静音开关,但我还没有尝试过。
使用环境模式播放视频和使用 PlayAndRecord模式在相机屏幕上录制视频,解决了我们案例中的问题。
应用程序中的代码:didFinishLaunchingWithOptions:
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
如果您必须在应用程序中使用摄像头或录制,则 viewWillAppear 中的代码会显示在 cameraController 上
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
viewWillDisappear 中的代码在 cameraController 上
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
使用这些行,我们的应用程序录制和播放视频和静音开关在 iOS8 和 iOS7 下都能完美运行!!!
对于斯威夫特
以下框架在设备中完美运行
https://github.com/akramhussein/静音
只需使用pod安装或从 Git 下载
pod 'Mute'
并使用如下代码
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
}
}
}