【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

 

原文地址:https://www.cnblogs.com/kaysun/p/5477956.html