有没有办法订阅音量按钮的按下事件?
在最近被苹果驳回之后
不要使用这个。现在苹果使用了一些补丁,如果应用程序使用任何私有的API,它将立即拒绝你的应用程序 - 尽管应该注意到App Store上已经有很多应用程序在使用这个功能并且仍然存在!
现在唯一的方法是准备一个AVAudioPlayer以播放但不播放([player prepareToPlay])。 这似乎可以负责根据摇杆按钮调整应用程序的音量。
目前没有其他公开的处理此问题的方法。
请阅读上面的说明
是的,使用MPVolumeView。
MPVolumeView *volume = [[[MPVolumeView alloc] initWithFrame:CGRectMake(18.0, 340.0, 284.0, 23.0)] autorelease];
[[self view] addSubview:volume];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
for (UIView *view in [volume subviews]){
if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) {
volumeViewSlider = view; //volumeViewSlider is a UIView * object
}
}
[volumeViewSlider _updateVolumeFromAVSystemController];
-(IBAction)volumeChanged:(id)sender{
[volumeViewSlider _updateVolumeFromAVSystemController];
}
这将给你一个滑块(与iPod中使用的相同),其值将根据手机音量而变化。
你会得到一个编译时警告,说视图可能无法响应 _updateVolumeFromAVSystemControl,但只需忽略它。
如果你只想要接收通知,我认为应该是这样的:
如果我错了,请纠正我,但我不认为这使用任何内部API。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
这个事件的详细信息在这里:http://www.cocoadev.com/index.pl?AVSystemController
其他回答似乎是基于这个 hack 的:http://blog.stormyprods.com/2008/09/proper-usage-of-mpvolumeview-class.html,这是一个现在已经修复的问题的解决方法。
但是我很确定,如果你只想获取通知而不是设置系统音量,你就可以像处理其他事件一样使用通知中心!!
请注意:自从苹果将音量上升操作添加到相机后,当一个UIImagePickerController
可见时,此通知会不会被发布。
UIImagePickerController
(例如相机)可见时,不会发送此通知。 - William Denniss#import <MediaPlayer/MediaPlayer.h>
和MPVolumeView *slide = [MPVolumeView new];
- ErpheusisInUse
和isOn
。isInUse
应该在某种通用应用程序设置中进行设置,并且总体上开关按钮支持。因此,无论类中的任何其他值如何,如果这个值为false
,当用户按下音量按钮时不会发生任何事情,并且实现尽可能保持清洁,不会不必要地影响系统音量级别。(阅读README中提到的问题,了解第一次打开按钮支持时可能发生的情况。)isOn
的意思是在需要按钮的时间内确切地为true
。您可以随时打开和关闭它,而不考虑isInUse
的当前值。PhysicalButton.shared.action = { /* do something */ }
该操作的类型为() -> Void
。在您初始化操作之前,不会发生任何故障。只是什么也不会发生。这种防御功能对我来说非常重要,因为使用音量按钮支持的视图只有在设置了按钮支持后才会创建。
要查看实际效果,您可以下载我正在使用的应用程序,这样可以快速免费使用。设置通常会操纵“物理按钮支持”。主要的秒表视图是实际上在进入视图时打开按钮处理,并在离开视图时关闭它。如果您有时间,您还会在设置 > 用户指南 > 选项:物理按钮支持中找到一个重要说明:
在特殊情况下,该应用程序可能没有机会在秒表视图外正确关闭音量按钮处理...
我将在Github README.md中添加完整说明。如果相关,请随意适应和重用它。
这种情况并不是特别异常,而且我还没有完全弄清楚问题出在哪里。当用户在音量按钮处于开启状态时关闭应用程序(或者你只是在Xcode中停止你的应用程序),物理按钮支持可能无法正确地从操作系统中移除。因此,你可能会得到两个内部处理程序实例,其中只有一个受你控制。因此,每次按下按钮都会导致两个甚至更多的调用到动作例程。我的包装器有一些保护代码来防止按钮过快调用。但这只是一个部分解决方案。修复需要进入底层处理程序,可惜我对此仍然了解太少,无法自行修复问题。OLD, FOR 1.0.1:
特别是,我对Swift解决方案很感兴趣。代码是用Objective-C编写的。为了节省某些人的研究时间,这就是我使用Cocoapods所做的全部(对于像我这样的蒟蒻):
pod 'JPSVolumeButtonHandler'
to the podfilepod install
on the command line#import <JPSVolumeButtonHandler.h>
to the bridging header fileSet up callbacks for the volume up and down buttons like so:
let volumeButtonHandler = JPSVolumeButtonHandler(
upBlock: {
log.debug("Volume up button pressed...")
// Do something when the volume up button is pressed...
}, downBlock: {
log.debug("Volume down button pressed...")
// Do something else for volume down...
})
class OptionalButtonHandler {
static var sharedInstance: OptionalButtonHandler?
private var volumeButtonHandler: JPSVolumeButtonHandler? = nil
private let action: () -> ()
var enabled: Bool {
set {
if !enabled && newValue {
// Switching from disabled to enabled...
assert(volumeButtonHandler == nil, "No leftover volume button handlers")
volumeButtonHandler = JPSVolumeButtonHandler(upBlock: {
log.debug("Volume up button pressed...")
self.action()
}, downBlock: {
log.debug("Volume down button pressed...")
self.action()
})
} else if enabled && !newValue {
log.debug("Disabling physical button...")
// The other way around: Switching from enabled to disabled...
volumeButtonHandler = nil
}
}
get { return (volumeButtonHandler != nil) }
}
/// For one-time initialization of this otherwise singleton class.
static func initSharedInstance(action: () -> ()) {
sharedInstance = OptionalButtonHandler(action: action)
}
private init(action: () -> ()) {
self.action = action
}
}
这样进行一次性设置:
OptionalButtonHandler.initSharedInstance({
// ...some UI action
})
OptionalButtonHandler.sharedInstance!.enabled = true // (false)
initSharedInstance()
之前不会访问.enabled
属性。AVSystemController
类和一些隐藏在UIApplication
中的方法。好的,
我看到了您的解决方案,不确定苹果是否会拒绝或接受使用 AVSystemController_SystemVolumeDidChangeNotification
。但是我有一个解决方法。
使用 MPVolumeView
的 UISlider
来注册 iPhone 硬件音量的任何更改,如下所示:
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectZero];
for (UIView *view in [volumeView subviews]) {
if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
self.volume_slider = (UISlider*)view;
break;
}
}
[volumeView sizeToFit];
#THIS IS THE MAIN LINE. ADD YOUR CALLBACK TARGET HERE
[self.volume_slider addTarget:self action:@selector(volumeListener:) forControlEvents:UIControlEventValueChanged];
[self addSubview:volumeView];
[volumeView setAlpha:0.0f];
-(void)volumeListener:(NSNotification*)notification {
#UPDATE YOUR UI ACCORDING OR DO WHATEVER YOU WANNA DO.
#YOU CAN ALSO GET THE SOUND STEP VALUE HERE FROM NOTIFICATION.
}
如果这对任何人有帮助,请告诉我。