MPVolumeSlider's MPVolumeControllerSystemDataSource not available in iOS 11.4

1.1k Views Asked by At

Today, I upgraded iOS to its latest 11.4. To set system volume, I am using the below method.

-(void) setVolumeLevel:(float)val {
    MPVolumeView *slide = [MPVolumeView new];
    UISlider *volumeViewSlider;

    for (UIView *view in [slide subviews]){
        if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) {
            volumeViewSlider = (UISlider *) view;
        }
    }
    volumeViewSlider.value=val;
}

But with 11.4, the volume is not getting set. Below is the log when I print. Please suggest, how to set system volume under iOS 11.4

<MPVolumeSlider: 0x1075bc3f0 dataSource: <MPVolumeControllerSystemDataSource: 0x1075be160 not available>
3

There are 3 best solutions below

4
Priyank Joshi On

Try setting up the volume for volumeViewSlider after you start any audio, somehow setting the audiosession to active does not help setting up the volume using MPVolume slider, once the audio starts (using AVAudioPlayer in my case), same code works.

So basically, in my case, after starting the view controller, directly changing the volume using slider does not work, while after starting any audio using AVAudioPlayer in view controller, slider works fine.

audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    audioPlayer.numberOfLoops = -1;
    audioPlayer.volume = 1.0;

    [audioPlayer play];

    if ([[MyGlobalManager sharedManager] getDeviceOS] > 11.3 && [[AVAudioSession sharedInstance] outputVolume] != 1.0f){
        [volumeViewSlider setValue:1.0f animated:YES];
        [volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
    }

Where, volumeSlider is obtained as :

MPVolumeView* volumeView = [[MPVolumeView alloc] init];

    //find the volumeSlider
    for (UIView *view in [volumeView subviews]){
        if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
            volumeViewSlider = (UISlider*)view;
            break;
        }
    }
[volumeViewSlider setValue:1.0f animated:YES];
    [volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
4
Northern Captain On

I faced the same problem and solved it by adding new MPVolumeView to my UIViewController view, otherwise it didn't set the volume anymore. As I added it to the controller I also need to set the volume view position to be outside of the screen.

I use setMaxVolume method here and it works any time, no matter if you played the sound before or not.

The code is in Swift 4:

let volumeControl = MPVolumeView(frame: CGRect(x: 0, y: 0, width: 120, height: 120))

override func viewDidLoad() {
   self.view.addSubview(volumeControl);
}

override func viewDidLayoutSubviews() {
   volumeControl.frame = CGRect(x: -120, y: -120, width: 100, height: 100);
}

func setMaxVolume() {
    let lst = volumeControl.subviews.filter{NSStringFromClass($0.classForCoder) == "MPVolumeSlider"}
    let slider = lst.first as? UISlider

    slider?.setValue(1, animated: false)
}
0
wormlxd On

The following code solves the problem

#pragma mark - GetVolume 
- (float)getCurrentVolume {
if (SystemVersion >= 7) {
    if (_volumeViewSlider) {
        return _volumeViewSlider.value;
    }
    MPVolumeView *volumeView = [[MPVolumeView alloc] init];
    for (UIView *view in [volumeView subviews]){
        if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
            _volumeViewSlider = (UISlider*)view;
            break;
        }
    }
    return _volumeViewSlider.value;
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    // 过期api写在这里不会有警告
    return [[MPMusicPlayerController applicationMusicPlayer] volume];
#pragma clang diagnostic pop
    }
}

#pragma mark - SetVolume
- (void)setVolume:(float)newVolume {
    newVolume = newVolume > 1 ? 1 : newVolume;
    newVolume = newVolume < 0 ? 0 : newVolume;

    if (SystemVersion >= 7) {
        [self.volumeViewSlider setValue:newVolume animated:NO];
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [[MPMusicPlayerController applicationMusicPlayer]                 setVolume:newVolume];
#pragma clang diagnostic pop
    }
}

Fisrt Addview UISlider * in your view. then getVolume and setVolume。