【ios】ios7以上 使用MPVolumeView获取系统音量
众所周知,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