iOS 7 使用 AVPlayer 在锁定屏幕上倒带歌曲

Posted

技术标签:

【中文标题】iOS 7 使用 AVPlayer 在锁定屏幕上倒带歌曲【英文标题】:iOS 7 rewind songs on lock screen using AVPlayer 【发布时间】:2013-09-11 05:05:50 【问题描述】:

我还没有找到如何从ios 7锁屏倒回歌曲的方法。音量滑块可用,所有按钮都可以正常工作,但上部滑块不可用!

AVPlayer 是我正在使用的类。

感谢任何帮助!

【问题讨论】:

【参考方案1】:

您需要在“正在播放的信息”中进行设置。

每当项目(轨道)发生变化时,执行类似的操作

NSMutableDictionary *nowPlayingInfo = [[NSMutableDictionary alloc] init];
[nowPlayingInfo setObject:track.artistName forKey:MPMediaItemPropertyArtist];
[nowPlayingInfo setObject:track.trackTitle forKey:MPMediaItemPropertyTitle];
...
[nowPlayingInfo setObject:[NSNumber numberWithDouble:self.player.rate] forKey:MPNowPlayingInfoPropertyPlaybackRate];
[nowPlayingInfo setObject:[NSNumber numberWithDouble:self.currentPlaybackTime] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nowPlayingInfo;

只要播放速率发生变化(播放/暂停),请执行

NSMutableDictionary *nowPlayingInfo = [[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo mutableCopy];
[nowPlayingInfo setObject:[NSNumber numberWithDouble:self.player.rate] forKey:MPNowPlayingInfoPropertyPlaybackRate];
[nowPlayingInfo setObject:[NSNumber numberWithDouble:self.currentPlaybackTime] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = nowPlayingInfo;

你可以这样获取当前播放时间:

- (NSTimeInterval)currentPlaybackTime 
  CMTime time = self.player.currentTime;
  if (CMTIME_IS_VALID(time)) 
    return time.value / time.timescale;
  
  return 0;

【讨论】:

这是因为如果您使用的是 MediaPlayer,他们使用的是 AVPlayer。 MPNowplayingInfo 可以与任何播放器一起使用。使用AVPlayer 这样做。 我也是这样做的,但是进度滑块还是不可用...我做错了吗? 抱歉,这并没有回答如何在锁定屏幕上使滑块可拖动以控制轨道内的位置的问题。默认音乐播放器具有垂直刻度线较大且可以拖动的功能。这是一个尴尬的界面,与滑动解锁功能冲突,很难抓住微小的刻度线(进度拇指),但它是默认应用程序可用的功能,似乎没有界面定制开发的音乐应用程序。 -rrh 部分有效。时间与播放器完美同步。但是可拖动仍然是一个问题。【参考方案2】:

您必须在 swift 中注册不同的事件,如下所示

    MPRemoteCommandCenter.shared().playCommand.addTarget(self, action: #selector(self.handleRemoteCommandActions))
    MPRemoteCommandCenter.shared().nextTrackCommand.addTarget(self, action: #selector(self.handleRemoteCommandActions))
    MPRemoteCommandCenter.shared().previousTrackCommand.addTarget(self, action: #selector(self.handleRemoteCommandActions))
    MPRemoteCommandCenter.shared().stopCommand.addTarget(self, action: #selector(self.handleRemoteCommandActions))
    MPRemoteCommandCenter.shared().pauseCommand.addTarget(self, action: #selector(self.handleRemoteCommandActions))
    MPRemoteCommandCenter.shared().changePlaybackPositionCommand.isEnabled = true
    MPRemoteCommandCenter.shared().changePlaybackPositionCommand.addTarget(self, action: #selector(self.handleChangePlaybackPositionRemoteCommandActions))

    let rcc = MPRemoteCommandCenter.shared()
    let skipBackwardIntervalCommand: MPSkipIntervalCommand? = rcc.skipBackwardCommand
    skipBackwardIntervalCommand?.isEnabled = false
    let skipForwardIntervalCommand: MPSkipIntervalCommand? = rcc.skipForwardCommand
    skipForwardIntervalCommand?.isEnabled = false
    let seekForwardCommand: MPRemoteCommand? = rcc.seekForwardCommand
    seekForwardCommand?.isEnabled = true
    rcc.changePlaybackPositionCommand.isEnabled = true
    rcc.changePlaybackRateCommand.isEnabled = true
    rcc.ratingCommand.isEnabled = true
    rcc.playCommand.isEnabled = true
    rcc.togglePlayPauseCommand.isEnabled = true

这里handleChangePlaybackPositionRemoteCommandActions这个方法将是你的方法,当scrubber(上滑块)改变它的值时,它必须管理寻找歌曲

它将如下所示:-

@objc func handleChangePlaybackPositionRemoteCommandActions(event:MPChangePlaybackPositionCommandEvent) -> MPRemoteCommandHandlerStatus

    print("handleChangePlaybackPositionRemoteCommandActions : \(event.positionTime)")
    self.appDelegate.audioPlayer?.seek(to: CMTime(seconds: event.positionTime, preferredTimescale: (self.appDelegate.audioPlayer?.currentItem?.currentTime().timescale)!))

    MPNowPlayingInfoCenter.default().nowPlayingInfo![MPNowPlayingInfoPropertyElapsedPlaybackTime] = event.positionTime

    return MPRemoteCommandHandlerStatus.success

【讨论】:

【参考方案3】:

我似乎也找不到添加拖动进度条以浏览当前播放歌曲的功能的方法,但是上面的 Chris 部分涵盖了让进度条显示的功能,但是您必须通过歌曲的持续时间以及其他信息以显示进度条。因此,除了 Chris 指出的内容之外,您还需要在 NSMutableDictionary 中添加以下内容:

[nowPlayingInfo setObject:[track valueForProperty: MPMediaItemPropertyPlaybackDuration]
                   forKey:MPMediaItemPropertyPlaybackDuration];

此外,您还可以长按前进和后退按钮并滚动播放音乐。在:

- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent

您可以查找这些事件子类型:

if (receivedEvent.subtype == UIEventSubtypeRemoteControlBeginSeekingBackward);
if (receivedEvent.subtype == UIEventSubtypeRemoteControlBeginSeekingForward);
if (receivedEvent.subtype == UIEventSubtypeRemoteControlEndSeekingBackward);
if (receivedEvent.subtype == UIEventSubtypeRemoteControlEndSeekingForward);

BeginSeekingForward 和 BeginSeekingBackward 分别由长按前进和后退按钮触发,当然 EndSeekingForward 和 EndSeekingBackward 事件子类型是手指离开按钮时。

当你得到这些事件子类型时,传递一个新的 NSDictionary 给

[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo

包含已包含在其中的所有信息(否则您未传入的属性将被清除)以及新的MPNowPlayingInfoPropertyElapsedPlaybackTimeMPNowPlayingInfoPropertyPlaybackRate。对于速率,您决定滚动音频的速度。 1 是正常速度,负值向后播放,所以 -2 是反向 2 倍正常速度。您必须将MPNowPlayingInfoCenter 的播放速率设置为与AVPlayer 的播放速率相同,否则它们将不会对齐。这就是为什么您还想通过当前时间。您可以通过以下方式获得:

[player currentTime]

所以要设置当前时间和速率:

[nowPlayingInfo setObject:[player currentTime]
                   forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[nowPlayingInfo setObject:[[NSNumber alloc] initWithFloat:10]
                   forKey:MPNowPlayingInfoPropertyPlaybackRate];

并设置播放器的速率:

[player setRate:10]

这应该使播放器和进度条在以 10 倍向前滚动速度滚动时对齐。因此,当您获得 BeginSeekingForward 事件子类型时,您将执行此操作。滚动结束时,将速率设置回 1,但仍将时间和其他信息传递给信息中心。对于 BeginSeekingBackward,只需使用负数作为比率。

我知道这是一篇旧帖子,但没有一个好的解决方案,我在搜索如何在锁定屏幕上获取音乐信息时遇到了这个帖子。我试图在 C# 中使用 Xamarin iOS 实现此功能,并在 http://www.sagorin.org/ios-playing-audio-in-background-audio/ 找到了一个很好的指南和示例 Objective-C 应用程序,其中包含其中的一些功能。但它没有滚动功能,也没有使用信息中心,它只是涵盖了从锁定屏幕处理暂停/播放。我使用 Xamarin 在 C# 中制作了一个示例应用程序,演示了向信息中心提供信息以及使用锁定和控制屏幕中的后退和前进按钮进行滚动,您可以在此处获取:https://github.com/jgold6/Xamarin-iOS-LockScreenAudio

我希望有人觉得这很有帮助。

【讨论】:

【参考方案4】:

以下是使用时间轴滑块执行此操作的方法:

首先必须正确设置nowPlayingInfo。你可以在任何地方找到如何做到这一点(不要忘记密钥MPNowPlayingInfoPropertyPlaybackRate);

其次是定义“滑动”的动作:

MPChangePlaybackPositionCommand *changePlaybackPositionCommand = [[MPRemoteCommandCenter sharedCommandCenter] changePlaybackPositionCommand];
[changePlaybackPositionCommand addTarget:self action:@selector(changePlaybackPositionEvent:)];
[[MPRemoteCommandCenter sharedCommandCenter].changePlaybackPositionCommand setEnabled:YES];

在action里面你可以做一些额外的事情,但是这里主要的是

[yourPlayer seekTo:event.positionTime completionHandler:^(BOOL finished) 
    [self updatePlaybackRateMetadata];
];

updatePlaybackRateMetadata 方法必须更新 MPNowPlayingInfoPropertyElapsedPlaybackTimeMPNowPlayingInfoPropertyPlaybackRate

很多时间过去了,但我希望这会对某人有所帮助!

【讨论】:

以上是关于iOS 7 使用 AVPlayer 在锁定屏幕上倒带歌曲的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 上的 MPNowPlayingInfoCenter AVPlayer

在锁定屏幕上检测播放结束 - AVPlayer

设备自动锁定时,AVPlayer 无法在 iPad 上运行

iOS AVPlayer seektotime 锁定在某些点

iOS:App停用后闹钟App如何播放声音?

IOS 7锁定屏幕Objective-C的警报本地通知