眾所周知,ios7已經廢棄了MPMusicPlayerController
ios7以下使用[[MPMusicPlayerController applicationMusicPlayer] setVolume:value];
那么ios7以上呢?使用MPVolumeView。
然而MPVolumeView有其局限性,MPVolumeView的subviews中的MPVolumeSlider的value值,即系統音量值(取值[0,1])
當我第一次在viewWillAppear的時候,獲取其中的MPVolumeSlider,會獲取不到;
所以嘗試在viewDidAppear,這一次很開心,獲取到了;
然而,之后發現在某些設備的一倍屏下,仍然獲取不到,或第一次獲取不到,第二次可以獲取到
所以,本文采用將MPVolumeView加入window.subview的形式,提前將MPVolumeView加入視圖,作為全局的一個視圖。
這樣的做法有助於分離音量與主業務邏輯,充分解耦
KEVolumeUtil.h
#define Volume_Change_Notification @"Volume_Change_Notification" @interface KEVolumeUtil : NSObject @property (nonatomic,assign) CGFloat volumeValue; + (KEVolumeUtil *) shareInstance; -(void)loadMPVolumeView; - (void)registerVolumeChangeEvent; - (void)unregisterVolumeChangeEvent; @end
KEVolumeUtil.m
#import "KEVolumeUtil.h" #import "KEAppDelegate.h" #import <MediaPlayer/MediaPlayer.h> #import <AVFoundation/AVFoundation.h> @interface KEVolumeUtil() @property (nonatomic, strong) MPVolumeView *mpVolumeView; @property (nonatomic, strong) UISlider *slider; @end @implementation KEVolumeUtil @synthesize volumeValue = _volumeValue; #pragma mark public methods +(KEVolumeUtil *) shareInstance { static KEVolumeUtil *instance = nil; static dispatch_once_t predicate; dispatch_once (&predicate, ^{ instance = [[self alloc] init]; }); return instance; } - (void) loadMPVolumeView { UIWindow *window = [KEAppDelegate globalAppDelegate].window; [window addSubview:self.mpVolumeView]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:NULL]; } - (void)registerVolumeChangeEvent { NSError *error; [[AVAudioSession sharedInstance] setActive:YES error:&error]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChangedNotification:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; } - (void)unregisterVolumeChangeEvent { [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; } #pragma mark private methods -(void) generateMPVolumeSlider { for (UIView *view in [self.mpVolumeView subviews]){ if ([view.class.description isEqualToString:@"MPVolumeSlider"]){ self.slider = (UISlider*)view; break; } } } #pragma mark setters -(void) setVolumeValue:(CGFloat) newValue { _volumeValue = newValue; //確保self.slider != nil if (!self.slider) { [self generateMPVolumeSlider]; } self.slider.value = newValue; } #pragma mark getters -(CGFloat) volumeValue { //確保self.slider != nil if (!self.slider) { [self generateMPVolumeSlider]; } return self.slider.value; } -(MPVolumeView *) mpVolumeView { if (!_mpVolumeView) { _mpVolumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(0, 50, 100, 100)]; _mpVolumeView.hidden = YES; } return _mpVolumeView; } #pragma mark notification - (void)volumeChangedNotification:(NSNotification *)notification { NSDictionary *userInfo = notification.userInfo; float value = [[userInfo objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"] floatValue]; self.volumeValue = value; [[NSNotificationCenter defaultCenter] postNotificationName:Volume_Change_Notification object:nil]; } @end