iOS 7:不推荐使用 MPMusicPlayerController 音量。现在如何更改设备音量?

Posted

技术标签:

【中文标题】iOS 7:不推荐使用 MPMusicPlayerController 音量。现在如何更改设备音量?【英文标题】:iOS 7: MPMusicPlayerController volume deprecated. How to change device volume now? 【发布时间】:2013-10-07 06:58:40 【问题描述】:

MPMusicPlayerController setVolume 为deprecated since ios 7

还有其他方法可以改变系统音乐音量吗?最好没有用户交互。 它的重要功能:自动增加 AppStore 中任何闹钟的音量。

【问题讨论】:

我也依赖此功能,因为我的用户希望能够设置和保存我的应用打开的音量。从开发人员的控制中移除这似乎是一件奇怪的事情。 有AVAudioPlayer:***.com/questions/5222464/…。我的问题是它是否可以播放 iPod 库中的歌曲。 同意,Apple 弃用了这些方法而没有提供适当的替代品,这很奇怪。 我注意到在 iOS 8.3 中,我的应用程序中的 MPMusicPlayerController 音量滑块根本不显示。它在早期的 iO​​S 版本中显示。没有对应用程序进行任何更改。有人在他们的应用中遇到过这个问题吗? @kzia 请为此问题创建单独的问题 【参考方案1】:

要准确回答您的问题: 是的,还有其他方法可以在无需用户交互的情况下更改系统音量。

直到最近,我一直认为只有使用 私有 API 才能以编程方式使用 MPVolumeView 更改音量。但我刚刚验证,改变 volumeSlider 的值和伪造滑块的 touchUP 事件是有效的:

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];

(当slider收到touchUP事件时,会调用自己的_commitVolumeChange方法,改变系统音量)

【讨论】:

对不起,如果我很愚蠢。我正在尝试将您的代码粘贴到我的 js 函数中。 Dreamweaver 向我抛出了一个红色的语法箭头。这是js代码还是别的什么? @Garavani 这是一个objective-c代码。而且跟js集成也不是那么简单。请在类似这样的教程中在线查找更多信息 - bignerdranch.com/blog/javascriptcore-example 这段代码,如所写,将引入一个问题:存储到“volumeView”中的对象的潜在泄漏 解决方法:Potential leak of an object stored into 'volumeView' 将 volumeView 移动到这样的属性中:@property (nonatomic, retain) MPVolumeView* volumeView; 然后从循环中以这种方式访问​​它:for (UIView *view in [self.volumeView subviews]) @ambientlight 我知道它不直接使用私有 API,但伪装用户交互作为触发私有 API _commitVolumeChange 的解决方法对我来说似乎有点冒险。还是)感谢你的建议! :)【参考方案2】:

在 Apple 认为适合撤销此决定之前,我发现了两种补救措施:

继续使用 volume 属性,在 iOS 7.0.2 下仍然可以使用 使用 AVAudioSession.outputVolume 在您的应用唤醒时读取音量,如果音量低于(或高于)用户指定的值,则会弹出包含 MPVolumeView 的警报。至少您的用户知道他们的闹钟(或其他)会安静地播放并有机会调整音量。或者,您可以非常清楚地显示音量级别,这样他们就不会感到意外。

【讨论】:

只应使用第二个选项 >= iOS 7.0。谢谢! :) 从 iOS 10 开始,你仍然可以使用 volume 属性!【参考方案3】:

这样做:

let masterVolumeSlider: MPVolumeView = MPVolumeView()

if let view = masterVolumeSlider.subviews.first as? UISlider

    view.value = 1.0


【讨论】:

还需要一个“导入媒体播放器” masterVolumeSlider.alpha = 0.01; self.view.addSubview(masterVolumeSlider) 还允许我在不显示操作系统音量计的情况下减少它 我最喜欢这个答案,因为它很优雅并且不需要使用内部类名。它似乎很可能在未来不会中断。【参考方案4】:

@Hurden,我写了一个 Swift 代码来实现 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
  

func rangeOfString 扩展字符串可以在这里找到Swift: A pure Swift method for returning ranges of a String instance (Xcode 6 Beta 5)

并使用这段代码让手势和mpvolumeslider一起工作

@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
  

【讨论】:

【参考方案5】:

显然一种改变系统音量的方法根本不显示任何内容

最棒的是它适用于 iOS 11

我是这样实现的:

1) 在所需的 ViewController 中创建两个变量

let volumeView = MPVolumeView()
var slider: UISlider?

2) 将下面的代码添加到您的 viewDidLoad 中

volumeView.alpha = 0.01
self.view.addSubview(volumeView)

if let view = volumeView.subviews.first as? UISlider 
    slider = view

3) 随时更改音量

slider?.value = 0.4

【讨论】:

【参考方案6】:

Swift 版本:

// 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
        
    

【讨论】:

【参考方案7】:

这个解决方案有点紧张,我觉得官方 API 不存在有点奇怪,但这是我根据环境光的帖子构建的 Swift 解决方案

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

【讨论】:

【参考方案8】:
let masterVolumeSlider  : MPVolumeView = MPVolumeView()

        if let view             = masterVolumeSlider.subviews.first as? UISlider

        view.value              = fVolume!

        view.sendActionsForControlEvents(UIControlEvents.TouchUpInside)

        

【讨论】:

以上是关于iOS 7:不推荐使用 MPMusicPlayerController 音量。现在如何更改设备音量?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 中不推荐使用音量 [重复]

iOS 7:不推荐使用“isa”

iOS 7:不推荐使用 MPMusicPlayerController 音量。现在如何更改设备音量?

Swift - 坐标不可用:从 iOS 7 开始不推荐使用 API

iOS 7 及更高版本 (8.4) 中不推荐使用 SegmentedControlStyle | Xcode 6.4

帮我选择合适的 iPhone 音频类 - MPMoviePlayer vs AVAudioPlayer vs MPMusicPlayer