如果屏幕锁定,点击暂停按钮时 avplayer 不会暂停
avplayer doesn't pause when clicked on pause button if screen is locked
如果应用程序正在播放音频并且phone屏幕被锁定,则控制屏幕如下所示。我无法对 avplayer
执行任何操作
在我的 appdelegate 中我实现了:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MPRemoteCommandCenter *rcc = [MPRemoteCommandCenter sharedCommandCenter];
[[rcc skipForwardCommand] setEnabled:NO];
[[rcc skipBackwardCommand] setEnabled:NO];
[[rcc nextTrackCommand] setEnabled:NO];
[[rcc previousTrackCommand] setEnabled:NO];
[[rcc skipForwardCommand] setEnabled:NO];
[[rcc skipBackwardCommand] setEnabled:NO];
rcc.playCommand.enabled = YES;
rcc.pauseCommand.enabled = YES;
[[MPRemoteCommandCenter sharedCommandCenter].playCommand addTarget:self action:@selector(play)];
[[MPRemoteCommandCenter sharedCommandCenter].pauseCommand addTarget:self action:@selector(pause)];
}
- (void) play {
[[MyVideoController instance] play];
}
- (void) pause {
[[MyVideoController instance] pause];
}
class MyVideoController 包括:
- (void) pause {
[self.avPlayer pause];
}
- (void) play {
[self.avPlayer play];
}
即使触发了这些方法(添加断点进行检查),也不会对 avplayer 采取任何操作。无论如何,avplayer 不会暂停。
有什么方法可以暂停 avplayer 吗?
编辑 1:
添加完整代码
在我的 AppDelegate 中:
- (void) remoteControlReceivedWithEvent: (UIEvent *) event {
[[ZVideoPlayerController instance] eventReceived:event];
if (event.type == UIEventTypeRemoteControl) {
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause: {
break;
}
case UIEventSubtypeRemoteControlPlay: {
[[ZVideoPlayerController instance] play];
break;
}
case UIEventSubtypeRemoteControlPause: {
[[ZVideoPlayerController instance] pause];
break;
}
default:
break;
}
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
}
我正在接收事件,但在 AVPLAYER 上调用暂停方法后音频没有暂停。
编辑 2:
PlayerController 中的实例声明 class
+ (instancetype)instance {
static id instance = nil;
if (instance == nil)
{
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^(void) {
NSAssert(instance == nil, @"Singleton instance is already allocated.");
instance = [[super allocWithZone:NULL] init];
});
}
return instance;
}
正在初始化 AVPlayer
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage: [UIImage imageNamed:@"Audio_Thumbnail_Play"]];
[songInfo setObject:title forKey:MPMediaItemPropertyTitle];
[songInfo setObject:@"100" forKey:MPMediaItemPropertyPlaybackDuration];
[songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
self.avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
在iOS 7.1 及更高版本中,使用共享的 MPRemoteCommandCenter 对象注册远程控制事件。使用共享命令中心对象时不需要调用此方法。
此方法使用响应者链启动远程控制事件的传递。远程控制事件起源于耳机和外部配件发出的命令,这些命令旨在控制应用程序呈现的多媒体。要停止接收远程控制事件,您必须调用 endReceivingRemoteControlEvents()。
为初始音频季节的 didfinishlunching 添加以下代码并获取远程控制事件:
// Initialize the AVAudioSession here.
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&myErr]) {
// Handle the error here.
NSLog(@"Audio Session error %@, %@", myErr, [myErr userInfo]);
}
else{
// Since there were no errors initializing the session, we'll allow begin receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
要接收命令,请使用此代码:
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlPreviousTrack:
break;
case UIEventSubtypeRemoteControlNextTrack:
break;
case UIEventSubtypeRemoteControlPlay:
[[MyVideoController instance] play];
break;
case UIEventSubtypeRemoteControlPause:
[[MyVideoController instance] pause];
break;
default:
break;
}
}
}
当应用程序为locked.For时,您需要注册远程通知以更新播放器状态:
在你的 AppDelegate 中添加这个,最好在 applicationDidEnterBackground:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
这在 applicationDidBecomeActive 中:
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
通过在 AppDelagate 中添加它来接收远程通知。当 phone 被锁定时,这将监听所有操作。
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl){
// Call method of your player where you want to make change (Pause , Paly),
// I am calling a shared view for example, Its up to your logic how you want to deal it
[[AudioPlayerView sharedPlayerView] remoteControlReceivedWithEvent:event];
}
}
然后得到你想要的事件并相应地更新状态
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl){
switch (event.subtype){
case UIEventSubtypeRemoteControlPlay:
[[MyVideoController instance] play];
break;
case UIEventSubtypeRemoteControlPause:
[[MyVideoController instance] pause];
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
// Check if state is playing , call pause else call play
break;
}
default:
break;
}
}
}
我找到了解决问题的办法。当我得到 avPlayer 的 nil 值时,我使用了我的 PageViewController class 来获取 PlayerController 的实例。然后我使用这个 playerController 的实例来播放和暂停我的 avplayer,因为这个实例持有对 avPlayer 的引用。
- (PlayerController *)getVideoController {
NSArray *controllers = [UtiliyClass getNavigationController].viewControllers;
PageViewController *pageController = nil;
for (UIViewController *cont in controllers) {
if ([cont isKindOfClass:[PageViewController class]]) {
pageController = (PageViewController *)cont;
break;
}
}
if (pageController == nil) {
return nil;
}
NSArray *objectsController =pageController.pageController.viewControllers;
PlayerController *videoPlayerController = nil;
for (UIViewController *item in objectsController) {
if ([item isKindOfClass:[PlayerController class]]) {
videoPlayerController = (PlayerController *)item;
break;
}
}
return videoPlayerController;
}
- (void) pause {
PlayerController *controller = [self getVideoController];
[controller.avPlayer pause];
}
- (void) play {
PlayerController *controller = [self getVideoController];
[controller.avPlayer play];
}
如果应用程序正在播放音频并且phone屏幕被锁定,则控制屏幕如下所示。我无法对 avplayer
执行任何操作在我的 appdelegate 中我实现了:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MPRemoteCommandCenter *rcc = [MPRemoteCommandCenter sharedCommandCenter];
[[rcc skipForwardCommand] setEnabled:NO];
[[rcc skipBackwardCommand] setEnabled:NO];
[[rcc nextTrackCommand] setEnabled:NO];
[[rcc previousTrackCommand] setEnabled:NO];
[[rcc skipForwardCommand] setEnabled:NO];
[[rcc skipBackwardCommand] setEnabled:NO];
rcc.playCommand.enabled = YES;
rcc.pauseCommand.enabled = YES;
[[MPRemoteCommandCenter sharedCommandCenter].playCommand addTarget:self action:@selector(play)];
[[MPRemoteCommandCenter sharedCommandCenter].pauseCommand addTarget:self action:@selector(pause)];
}
- (void) play {
[[MyVideoController instance] play];
}
- (void) pause {
[[MyVideoController instance] pause];
}
class MyVideoController 包括:
- (void) pause {
[self.avPlayer pause];
}
- (void) play {
[self.avPlayer play];
}
即使触发了这些方法(添加断点进行检查),也不会对 avplayer 采取任何操作。无论如何,avplayer 不会暂停。
有什么方法可以暂停 avplayer 吗?
编辑 1: 添加完整代码
在我的 AppDelegate 中:
- (void) remoteControlReceivedWithEvent: (UIEvent *) event {
[[ZVideoPlayerController instance] eventReceived:event];
if (event.type == UIEventTypeRemoteControl) {
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause: {
break;
}
case UIEventSubtypeRemoteControlPlay: {
[[ZVideoPlayerController instance] play];
break;
}
case UIEventSubtypeRemoteControlPause: {
[[ZVideoPlayerController instance] pause];
break;
}
default:
break;
}
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
}
我正在接收事件,但在 AVPLAYER 上调用暂停方法后音频没有暂停。
编辑 2: PlayerController 中的实例声明 class
+ (instancetype)instance {
static id instance = nil;
if (instance == nil)
{
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^(void) {
NSAssert(instance == nil, @"Singleton instance is already allocated.");
instance = [[super allocWithZone:NULL] init];
});
}
return instance;
}
正在初始化 AVPlayer
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage: [UIImage imageNamed:@"Audio_Thumbnail_Play"]];
[songInfo setObject:title forKey:MPMediaItemPropertyTitle];
[songInfo setObject:@"100" forKey:MPMediaItemPropertyPlaybackDuration];
[songInfo setObject:albumArt forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
self.avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
在iOS 7.1 及更高版本中,使用共享的 MPRemoteCommandCenter 对象注册远程控制事件。使用共享命令中心对象时不需要调用此方法。 此方法使用响应者链启动远程控制事件的传递。远程控制事件起源于耳机和外部配件发出的命令,这些命令旨在控制应用程序呈现的多媒体。要停止接收远程控制事件,您必须调用 endReceivingRemoteControlEvents()。
为初始音频季节的 didfinishlunching 添加以下代码并获取远程控制事件:
// Initialize the AVAudioSession here.
if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&myErr]) {
// Handle the error here.
NSLog(@"Audio Session error %@, %@", myErr, [myErr userInfo]);
}
else{
// Since there were no errors initializing the session, we'll allow begin receiving remote control events
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}
要接收命令,请使用此代码:
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlPreviousTrack:
break;
case UIEventSubtypeRemoteControlNextTrack:
break;
case UIEventSubtypeRemoteControlPlay:
[[MyVideoController instance] play];
break;
case UIEventSubtypeRemoteControlPause:
[[MyVideoController instance] pause];
break;
default:
break;
}
}
}
当应用程序为locked.For时,您需要注册远程通知以更新播放器状态:
在你的 AppDelegate 中添加这个,最好在 applicationDidEnterBackground:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
这在 applicationDidBecomeActive 中:
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
通过在 AppDelagate 中添加它来接收远程通知。当 phone 被锁定时,这将监听所有操作。
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl){
// Call method of your player where you want to make change (Pause , Paly),
// I am calling a shared view for example, Its up to your logic how you want to deal it
[[AudioPlayerView sharedPlayerView] remoteControlReceivedWithEvent:event];
}
}
然后得到你想要的事件并相应地更新状态
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl){
switch (event.subtype){
case UIEventSubtypeRemoteControlPlay:
[[MyVideoController instance] play];
break;
case UIEventSubtypeRemoteControlPause:
[[MyVideoController instance] pause];
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
// Check if state is playing , call pause else call play
break;
}
default:
break;
}
}
}
我找到了解决问题的办法。当我得到 avPlayer 的 nil 值时,我使用了我的 PageViewController class 来获取 PlayerController 的实例。然后我使用这个 playerController 的实例来播放和暂停我的 avplayer,因为这个实例持有对 avPlayer 的引用。
- (PlayerController *)getVideoController {
NSArray *controllers = [UtiliyClass getNavigationController].viewControllers;
PageViewController *pageController = nil;
for (UIViewController *cont in controllers) {
if ([cont isKindOfClass:[PageViewController class]]) {
pageController = (PageViewController *)cont;
break;
}
}
if (pageController == nil) {
return nil;
}
NSArray *objectsController =pageController.pageController.viewControllers;
PlayerController *videoPlayerController = nil;
for (UIViewController *item in objectsController) {
if ([item isKindOfClass:[PlayerController class]]) {
videoPlayerController = (PlayerController *)item;
break;
}
}
return videoPlayerController;
}
- (void) pause {
PlayerController *controller = [self getVideoController];
[controller.avPlayer pause];
}
- (void) play {
PlayerController *controller = [self getVideoController];
[controller.avPlayer play];
}