iOS 8のボリュームアップ/ダウンボタンの押下をキャプチャする最良/最もクリーンな方法は何ですか?
理想的には、キー入力をキャプチャし、システムボリュームが変化しないようにします(少なくとも、ボリューム変更HUDが表示されないようにします)。
廃止されたメソッドを使用し、iOS 8ではまったく機能しないように思われる古い回答がいくつかあります。これは iOS 8固有のもの も機能しませんでした。
この RBVolumeButtons オープンソースクラスは、iOS 8でも動作しないようです。
Swiftの場合、viewControllerクラスで次のコードを使用できます。
let volumeView = MPVolumeView(frame: CGRectMake(-CGFloat.max, 0.0, 0.0, 0.0))
self.view.addSubview(volumeView)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(volumeChanged(_:)), name: "AVSystemController_SystemVolumeDidChangeNotification", object: nil)
次に、この関数を追加します
func volumeChanged(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let volumeChangeType = userInfo["AVSystemController_AudioVolumeChangeReasonNotificationParameter"] as? String {
if volumeChangeType == "ExplicitVolumeChange" {
// your code goes here
}
}
}
}
このコードは、ユーザーによる明示的なボリューム変更アクションを検出します。明示的なアクションをチェックしなかった場合、この関数は定期的に自動的に呼び出されます。
このコードはシステムボリュームの変更を妨げません
最初にAVFoundationおよびMediaPlayerFrameworkを追加してから、以下のコードを使用して上下ボタンの押下を検出し、
-(void)viewWillAppear:(BOOL)animated
{
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
[audioSession setActive:YES error:nil];
[audioSession addObserver:self
forKeyPath:@"outputVolume"
options:0
context:nil];
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqual:@"outputVolume"]) {
float volumeLevel = [[MPMusicPlayerController applicationMusicPlayer] volume];
NSLog(@"volume changed! %f",volumeLevel);
}
}
for Swift 3:(忘れずに追加してください:import MediaPlayer ..)
override func viewDidLoad() {
super.viewDidLoad()
let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 40, width: 300, height: 30))
self.view.addSubview(volumeView)
// volumeView.backgroundColor = UIColor.red
NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged(notification:)),
name: NSNotification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification"),
object: nil)
}
func volumeChanged(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let volumeChangeType = userInfo["AVSystemController_AudioVolumeChangeReasonNotificationParameter"] as? String {
if volumeChangeType == "ExplicitVolumeChange" {
// your code goes here
}
}
}
}
....
Objective-Cバージョン(通知を使用):
#import <MediaPlayer/MPVolumeView.h>
#import <AVFoundation/AVFoundation.h>
@interface ViewController () {
UISlider *volumeViewSlider;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self startTrackingVolumeChanges];
}
- (void)dealloc
{
[self stopTrackingVolumeChanges];
}
#pragma mark - Start Tracking Volume Changes
- (void)startTrackingVolumeChanges
{
[self setupVolumeViewSlider];
[self addObserver];
[self activateAudioSession];
}
- (void)setupVolumeViewSlider
{
MPVolumeView *volumeView = [[MPVolumeView alloc] init];
for (UIView *view in [volumeView subviews]) {
if ([view.class.description isEqualToString:@"MPVolumeSlider"]) {
volumeViewSlider = (UISlider *)view;
break;
}
}
}
- (void)addObserver
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
}
- (void)activateAudioSession
{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
NSError *error;
BOOL success = [audioSession setActive:YES error:&error];
if (!success) {
NSLog(@"Error activating audiosession: %@", error);
}
}
#pragma mark - Observing Volume Changes
- (void)volumeChanged:(NSNotification *)notification
{
NSString *volumeChangeType = notification.userInfo[@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"];
if ([volumeChangeType isEqualToString:@"ExplicitVolumeChange"]) {
float volume = volumeViewSlider.value;
NSLog(@"volume = %f", volume);
}
}
#pragma mark - Stop Tracking Volume Changes
- (void)stopTrackingVolumeChanges
{
[self removeObserver];
[self deactivateAudioSession];
volumeViewSlider = nil;
}
- (void)removeObserver
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
}
- (void)deactivateAudioSession
{
dispatch_async(dispatch_get_main_queue(), ^{
NSError *error;
BOOL success = [[AVAudioSession sharedInstance] setActive:NO error:&error];
if (!success) {
NSLog(@"Error deactivating audiosession: %@", error);
}
});
}
@end
ああ、詳細については、オーディオセッションサービスリファレンスを参照してください。 AudioSessionInitializeでオーディオセッションを開始し、AudioSessionSetActiveでアクティブにし、AudioSessionAddPropertyListenerでボリュームの変更をリッスンし、AudioSessionPropertyListenerタイプのコールバックを渡す必要があります。
このWebサイトには良い記事があります: http://fredandrandall.com/blog/2011/11/18/taking-control-of-the-volume-buttons-on-ios-like-camera/