iOS 7如何使用AVPlayer在锁屏界面倒带音乐?

7

我还没有找到在iOS 7的锁定屏幕上如何倒带歌曲的方法。音量滑块可用,所有按钮正常工作,但上部滑块不可用!

我使用的是AVPlayer类。

非常感谢任何帮助!

4个回答

11

你需要在“现在播放信息”中进行设置。

每当项目(曲目)更改时,就执行类似以下操作:

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。 - daihovey
3
MPNowplayingInfo 可以与任何播放器一起使用,用 AVPlayer 实现即可。 - chris
我也是用同样的方法,但进度条仍然不可用... 我做错了吗? - iWheelBuy
4
抱歉,这并没有回答如何在锁屏状态下使滑块可拖动以控制音轨位置的问题。默认音乐播放器具备此功能,其垂直刻度线更大且可拖动。虽然这是一个笨拙的界面,与滑动解锁功能冲突,并且很难抓住微小的刻度线(进度滑块),但它是默认应用程序提供的功能,似乎没有为自定义开发的音乐应用程序设计这种界面。-rrh - Richie Hyatt
嘿,以上代码在锁屏时自动转发不起作用。我们是否应该通过实现NSTimer并在seekend处停止它来改变播放器时间self.player.currentTime =?something? - Ankish Jain
显示剩余2条评论

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方法将是您管理歌曲搜索时必须使用的方法,当滑块(上部滑块)更改其值时。

它会像下面这样:

@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
}

1

以下是如何使用时间轴滑块完成此操作的方法:

首先,必须正确设置nowPlayingInfo。您可以在任何地方找到如何执行此操作(不要忘记关键字MPNowPlayingInfoPropertyPlaybackRate);

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

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

在这个操作中,您可以进行一些其他的事情,但主要的目标是

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

updatePlaybackRateMetadata方法必须更新MPNowPlayingInfoPropertyElapsedPlaybackTimeMPNowPlayingInfoPropertyPlaybackRate

虽然时间过去了很久,但我希望这可以帮助到某些人!


1
我似乎找不到一种方法来添加拖动进度条的功能,但是让进度条显示部分由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,只需使用负数作为速率即可。
我知道这是一个旧帖,但并没有一个好的解决方案,而我在寻找如何将音乐信息放到锁屏界面时遇到了这个线程。我试图用Xamarin iOS中的C#实现此功能,并在http://www.sagorin.org/ios-playing-audio-in-background-audio/找到了一份很好的指南和Objective-C样本应用程序,其中包含了部分此功能。但它没有滚动功能,也没有使用信息中心,只涵盖了从锁屏界面处理暂停/播放。我用Xamarin制作了一个演示向信息中心提供信息并通过锁定和控制屏幕的后退和前进按钮进行滚动的示例应用程序,在这里可以获得:https://github.com/jgold6/Xamarin-iOS-LockScreenAudio
我希望有人会发现这有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接