I want to change the device volume on iOS (iphone).
I know that i can change the volume of music library with this lines below:
//implement at firs
To answer brush51's question:
How can i do that? just change the DEVICE volume?
As 0x7fffffff suggested:
You cannot change device volume programatically, however MPVolumeView (volume slider) is there to change device volume but only through user interaction.
So, Apple recommends using MPVolumeView
, so I came up with this:
Add volumeSlider
property:
@property (nonatomic, strong) UISlider *volumeSlider;
Init MPVolumeView
and add somewhere to your view (can be hidden, without frame, or empty because of showsRouteButton = NO
and showsVolumeSlider = NO
):
MPVolumeView *volumeView = [MPVolumeView new];
volumeView.showsRouteButton = NO;
volumeView.showsVolumeSlider = NO;
[self.view addSubview:volumeView];
Find and save reference to UISlider
:
__weak __typeof(self)weakSelf = self;
[[volumeView subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UISlider class]]) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.volumeSlider = obj;
*stop = YES;
}
}];
Add target action for UIControlEventValueChanged
:
[self.volumeSlider addTarget:self action:@selector(handleVolumeChanged:) forControlEvents:UIControlEventValueChanged];
And then detect volume changing (i.e. by the hardware volume controls):
- (void)handleVolumeChanged:(id)sender
{
NSLog(@"%s - %f", __PRETTY_FUNCTION__, self.volumeSlider.value);
}
and also other way around, you can set volume by:
self.volumeSlider.value = < some value between 0.0f and 1.0f >;
Hope this helps (and that Apple doesn't remove MPVolumeSlider from MPVolumeView).
Here is a little wrapper class that can set the system volume and aslo notify you on any changes (pass your own change responder to setTarget:action:).
Edit: if you hide the MPVolumeView control or don't add it as a subview, then the system will show the default volume square in the middle of the screen whenever you change the volume programmatically. If you don't like what the system does, the solution is to set view coordinates outside of the screen. I edited my code below a bit to reflect this.
@import MediaPlayer;
@interface SysVolumeControl : MPVolumeView
@property (nonatomic) float value; // from 0 to 1.0
- (void)setTarget:(id)target action:(SEL)action;
@end
@implementation SysVolumeControl
{
UISlider* _slider;
}
- (id)init
{
if (self = [super initWithFrame:CGRectMake(-300, 0, 200, 50)])
{
for (UIView* view in self.subviews)
{
if ([view isKindOfClass:UISlider.class])
{
_slider = (UISlider*)view;
break;
}
}
}
return self;
}
- (float)value
{ return _slider.value; }
- (void)setValue:(float)value
{ _slider.value = value; }
- (void)setTarget:(id)target action:(SEL)action
{ [_slider addTarget:target action:action forControlEvents:UIControlEventValueChanged]; }
@end
Then create an instance and use it:
SysVolumeControl* sysVolumeControl = [SysVolumeControl new];
[myView addSubview:sysVolumeControl];
sysVolumeControl.value = 1.0;
[sysVolumeControl setTarget:self action:@selector(mySysVolumeResponder:)];
You have to use applicationMusicPlayer instead of iPodMusicPlayer to set the system volume:
#import <MediaPlayer/MediaPlayer.h>
musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
musicPlayer.volume = 1; // max volume
musicPlayer.volume = 0; // min volume (mute)
musicPlayer.volume = 0.0625; // 1 bar on the overlay volume display
This (Swift) solution worked great for me: http://weimenglee.blogspot.com/2015/07/ios-tip-programmatically-adjust-device.html
import MediaPlayer
let volumeView = MPVolumeView()
if let view = volumeView.subviews.first as? UISlider{
view.value = 0.1 //---0 t0 1.0---
}
Creating MPVolumeView on the fly to get the slider and set the volume doesn't work in iOS 11.4 anymore. I solved the issue by adding new MPVolumeView to my UIViewController view, otherwise it didn't set the volume. As I added it to the controller I also need to set the volume view position to be outside of the screen.
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)
}
The app should not change device global settings and you should not do that. User can do that using standard iOS features.
Instead, if you playing a sound/video, then use player's volume
:
var player: AVPlayer!
...
player.volume = 0.5 // 50% level