有没有办法订阅音量按钮按事件?
答案 0 :(得分:21)
最近Apple拒绝后
不要使用它。 Apple现在使用一些补丁,如果它使用任何私有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,但只是忽略它。
答案 1 :(得分:17)
如果您只是想收到通知,我认为是这样的:
如果我错了,请纠正我,但我不相信这会使用任何内部API。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(volumeChanged:)
name:@"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
此活动的详情如下:http://www.cocoadev.com/index.pl?AVSystemController
这里的其他回复似乎是基于这个黑客:http://blog.stormyprods.com/2008/09/proper-usage-of-mpvolumeview-class.html这是一个现在修复的bug的解决方法。
但是我很确定你想要做的只是 GET 通知,而不是 SET 系统卷,你可以像使用通知中心一样任何其他事件!!
请注意:由于Apple向相机添加了音量调节操作,因此当UIImagePickerController
可见时,此通知不。
答案 2 :(得分:1)
如果您愿意使用私有API,我会a patch to Wolf3d添加您正在寻找的功能。它使用私有AVSystemController
类和UIApplication
答案 3 :(得分:1)
好,
所以我看到了你的解决方案,并且不确切地知道Apple是否会拒绝或接受使用AVSystemController_SystemVolumeDidChangeNotification
。但我有一个解决方法。
使用UISlider
MPVolumeView
来注册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.
}
如果这有助于任何人,请告诉我。
答案 4 :(得分:1)
我在研究上面提到的所有资源以及其他线程中找到的最简单,功能最完善的方法是:JPSVolumeButtonHandler(除了作为用户之外我不介入。但是非常感谢给责任人!)
编辑:版本1.0.2附带了一些重大更改/增强功能。我将首先留下1.0.1的答案。
我放置了一个样本包装类,您可以按原样部署它,或者用于学习JPSVolumeButtonHandler,希望在separate Github repository real quick here中正确使用。
这里是如何使用包装器的(我一到达就将它添加到存储库中):
单例类有两个标志:isInUse
和isOn
。 isInUse
旨在通常在某些常规应用设置和开关按钮支持中设置。
因此,无论类中是否有任何其他值,如果这是false
,当用户按下音量按钮时,不会发生任何事情,并且实现确保尽可能保持干净并且不会不必要地影响系统音量。 (阅读README中提到的问题,了解第一次启用按钮支持时可能发生的情况。)
isOn
在需要按钮的持续时间内完全是true
。您可以打开和关闭它,而不考虑isInUse
。
在初始化按下音量按钮时应该发生的操作的任何视图中,设置操作如下:
PhysicalButton.shared.action = {/ *做点什么* /}
该操作的类型为() -> Void
。在你初始化动作之前,什么都不会破坏。什么都不会发生。这种防御功能对我来说很重要,因为只有在设置了按钮支持后才能创建使用音量按钮支持的视图。
为了看到实际行动,你可以download the app我真正快速地免费使用它。设置操纵"物理按钮支持"一般来说。主秒表视图是在进入视图时实际切换按钮处理的视图,而在离开视图时关闭。如果您找到时间,您还可以在设置>中找到重要提示。用户指南>选项:物理按钮支持:
在特殊情况下,应用可能无法正常使用 在秒表视图外部切换音量按钮处理...
我将完整的注释添加到Github README.md。如果它与您的情况相关,请随意调整和重复使用。
情况实际上并不是那么特别,而且我还没有完全弄明白什么是错的。当用户在打开音量按钮时杀死应用程序(或者您只是在Xcode中停止应用程序)时,可能无法从操作系统中正确删除物理按钮支持。因此,您最终可以得到两个内部处理程序实例,其中只有一个是您可以控制的。因此,每按一次按钮都会导致两次或更多次调用操作例程。我的包装器有一些监护代码,以防止按钮调用太快。但那只是部分解决方案。修复需要进入底层处理程序,遗憾的是我仍然对自己尝试解决问题的理解太少了。
OLD,FOR 1.0.1:
特别是,我的兴趣在于Swift解决方案。代码在Objective-C中。为了节省一些研究,这就是我使用Cocoapods(对我这样的假人)所做的一切:
pod 'JPSVolumeButtonHandler'
添加到podfile pod install
#import <JPSVolumeButtonHandler.h>
添加到桥接头文件设置音量增大和减小按钮的回调,如下所示:
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
}
}
此处上下音量按钮只有一个常用操作。 initSharedInstance()
是必要的,因为我的操作包括对UI元素(视图)的引用,该元素仅在应用启动后在某个用户相关点设置。
一次性设置如下:
OptionalButtonHandler.initSharedInstance({
// ...some UI action
})
有选择地启用/禁用如下:
OptionalButtonHandler.sharedInstance!.enabled = true // (false)
(请注意,我的代码逻辑确保.enabled
之前永远不会访问initSharedInstance()
。)
我在(required!)测试设备上运行Xcode 7.3和iOS 9.3.2。
期待了解Apple如何重置超重的音量按钮。至少我的应用程序确保微创和按钮使用真的很有意义。它不是相机应用程序,但类似的应用程序之前使用过物理音量按钮(甚至不太好)。