5

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>
aios
  • 405
  • 5
  • 14

3 Answers3

1

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)
}
Northern Captain
  • 1,147
  • 3
  • 25
  • 32
  • I would like to change/modify the system volume without user interaction. I don't want to show volume slider to the user. – aios Jun 07 '18 at 09:09
  • Has anyone got this working with Objective-C? I tried the equivalent of this Swift4 code, but it does nothing. The only thing that works so far is resorting to the deprecated: `MPMusicPlayerController *musicPlayer = [MPMusicPlayerController applicationMusicPlayer]; if ([musicPlayer respondsToSelector:@selector(setVolume:)]) [musicPlayer setVolume:1.f];` – Al. Jun 07 '18 at 12:22
  • The answer is here: https://stackoverflow.com/questions/50737943/how-to-change-volume-programmatically-on-ios-11-4 – Al. Jun 07 '18 at 13:07
  • This method won't show any slider to the user as I set it to be outside of the screen (invisible) in viewDidLayoutSubviews() – Northern Captain Jun 08 '18 at 21:01
0

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];
Priyank Joshi
  • 300
  • 1
  • 4
  • 17
  • 1
    Not working. MPVolumeControllerSystemDataSource is still showing not available under iOS11.4 even when audio is playing. Did you test the code under 11.4? When we call the above method [self setVolumeLevel:1.0]; volume setting to high in your case? – aios Jun 04 '18 at 12:31
  • Yes, I am using the same code to set the volume up. Just after I play an audio and it works, posting my code snippet. – Priyank Joshi Jun 05 '18 at 02:24
  • The same code is working in iOS 11.3 and below but not in iOS 11.4. – aios Jun 05 '18 at 08:57
  • Weird, works for me in 11.4, I don't make changes after media started in 11.3. – Priyank Joshi Jun 05 '18 at 09:00
0

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。

wormlxd
  • 514
  • 3
  • 7