MPMusicPlayerController setVolume is deprecated since iOS 7
Is there any other way to change system music volume? Preferably without user interaction. Its important feature: to increase volume automatically for any alarm clock from AppStore.
MPMusicPlayerController setVolume is deprecated since iOS 7
Is there any other way to change system music volume? Preferably without user interaction. Its important feature: to increase volume automatically for any alarm clock from AppStore.
To answer you question exactly: Yes there is other way to change system volume without user interaction.
Until recent times I used to think that changing volume using MPVolumeView programmatically is possible only using private API. But I have just verified, that changing the value of volumeSlider and faking slider's touchUP event works:
MPVolumeView* volumeView = [[MPVolumeView alloc] init];
//find the volumeSlider
UISlider* volumeViewSlider = nil;
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];
(When slider receives touchUP event, it will invoke _commitVolumeChange
method on itself, which will change the system volume)
Potential leak of an object stored into 'volumeView'
Move volumeView into a property like so: @property (nonatomic, retain) MPVolumeView* volumeView;
Then access it this way from the loop: for (UIView *view in [self.volumeView subviews]){
–
Homecoming The system wide output volume can be set directly only by the user; to provide volume control in your app, use the MPVolumeView class.
Therefore instead of doing this programatically, show that slider to the user and let him adjust the volume –
Lasala [MPMusicPlayerController systemMusicPlayer].volume = newVolume;
in iOS 7 suggests that only the user should have control of the system volume. –
Lasala _commitVolumeChange
seems a bit risky to me. Thanks for the suggestion though! :) –
Lasala Until Apple sees fit to rescind this decision there are two remedies I have discovered:
Just do this:
let masterVolumeSlider: MPVolumeView = MPVolumeView()
if let view = masterVolumeSlider.subviews.first as? UISlider{
view.value = 1.0
}
masterVolumeSlider.alpha = 0.01; self.view.addSubview(masterVolumeSlider)
also allowed me to reduce it without showing the OS volume meter –
Decennium @Hurden, I wrote a Swift code to implement the MPVolumeSlider:
for view in mpVolumeView.subviews {
let uiview: UIView = view as UIView
//println("\(uiview.description)")
if uiview.description.rangesOfString("MPVolumeSlider").first != nil {
mpVolumeSilder = (uiview as UISlider)
currentDeviceVolume = mpVolumeSilder!.value
return
}
}
The func rangeOfString extension String can be found here Swift: A pure Swift method for returning ranges of a String instance (Xcode 6 Beta 5)
And use this code to let the gesture and mpvolumeslider work together
@IBAction func handlePan(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translationInView(self.view)
let dx = (translation.x-lastTranslationX)
let volumeChanged = Float(dx / mpVolumeView.frame.width)
currentDeviceVolume = currentDeviceVolume + Float(volumeChanged)
if currentDeviceVolume > 1 {
currentDeviceVolume = 1
} else if currentDeviceVolume < 0 {
currentDeviceVolume = 0
}
mpVolumeSilder!.value = currentDeviceVolume
if recognizer.state == .Changed {
lastTranslationX = translation.x
}
if recognizer.state == .Ended || recognizer.state == .Began {
lastTranslationX = 0
}
}
Apparently there is a way to change the system volume without displaying anything at all.
And best of all it works on iOS 11.
Here's how I've achieved it:
1) Create two variables in desired ViewController
let volumeView = MPVolumeView()
var slider: UISlider?
2) Add the code below into your viewDidLoad
volumeView.alpha = 0.01
self.view.addSubview(volumeView)
if let view = volumeView.subviews.first as? UISlider {
slider = view
}
3) Change volue whenever you need
slider?.value = 0.4
Swift Version:
// Outlet added in Storyboard (Add UIView then set class to MPVolumeView)
@IBOutlet weak var mpVolumeView: MPVolumeView!
// Get volume slider within MPVolumeView
for subview in self.mpVolumeView.subviews {
if (subview as UIView).description.rangeOfString("MPVolumeSlider") != nil {
// Set volume
let volumeSlider = subview as UISlider
volumeSlider.value = 1
// Works with or without the following line:
// volumeSlider.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
break
}
}
This solution makes a bit nervous and I think its a bit odd an official API doesn't exist but here is my Swift solution built off of ambientlight's post
var _volumeView = MPVolumeView()
var _volumeSlider : UISlider? = nil
self.view.addSubview(_volumeView)
_volumeView.hidden = true
var i = 0
while i < _volumeView.subviews.count {
if let _r = _volumeView.subviews[i] as? UISlider {
_volumeSlider = _r
break
}
++i
}
let masterVolumeSlider : MPVolumeView = MPVolumeView()
if let view = masterVolumeSlider.subviews.first as? UISlider{
view.value = fVolume!
view.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
}
© 2022 - 2024 — McMap. All rights reserved.