- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试编写一个简单的个人广播应用程序,但遇到了一个烦人的问题。
我尝试使用 AVPlayer 从远程服务器播放 .pls(流)文件,我成功地让它工作了。我现在可以播放流,但正如我在标题中提到的,当应用程序处于后台时,我无法远程控制播放/暂停选项。
我在 Internet 上搜索了很多有关该主题的内容,并找到了两个解决方案。
1- 如 Apple 的 Remote Control Events文档,使用“MPRemoteCommandCenter”类来处理这个问题,但是对于这个解决方案,我找不到任何好的解释来说明我将如何使用 AVPlayer。这让我想到了第二个解决方案,因为我不知道如何使用 MPRemoteCommandCenter 类。
2- 几乎所有人都提到过remoteControlReceivedWithEvent: 方法。但是,当我尝试使用该方法时,我无法得到回应。我的 remoteControlReceivedWithEvent: 方法从未被调用过。这是我实现行为的代码:
我有两个类,一个名为 EGPlayRadio.m,其中包含 AVPlayer 和 AVAudioSession 内容,另一个是 EGMainMenuViewController.m,它显示播放按钮和暂停按钮以流式传输 radio 。
我注意在调用 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents] 方法之前先调用 [AVSession sharedInstance]。
我还注意到从项目的build设置中授予应用后台音频播放权限。
但是,在网上搜索了很多之后,我找不到适合我的问题的解决方案。这是我实现的两个类:
EGPlayRadio.m
#import "EGPlayRadio.h"
#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>
@interface EGPlayRadio () <AVAudioPlayerDelegate>
@property (nonatomic, strong) AVAudioSession *audioSession;
@property (nonatomic, strong) AVPlayer *player;
@end
@implementation EGPlayRadio
- (id)initDefault
{
self = [super init];
if (self)
{
_audioSession = [AVAudioSession sharedInstance];
[_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
NSURL *url = [[NSURL alloc] initWithString:@"http://LINK-OF-THE-PLS-FILE"];
_player = [[AVPlayer alloc] initWithURL:url];
}
return self;
}
- (void)playRadio
{
[self.player play];
}
- (void)pauseRadio
{
[self.player pause];
}
EGMainMenuViewController.m
@interface EGRMainMenuViewController ()
@property (nonatomic, strong) IBOutlet UIButton *playButton;
@property (nonatomic, strong) IBOutlet UIButton *pauseButton;
@property (nonatomic, strong) EGPlayRadio *radioControl;
@end
@implementation EGRMainMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.radioControl = [[EGPlayRadio alloc] initDefault];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
self.pauseButton.enabled = NO;
self.pauseButton.alpha = 0.3f;
}
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (IBAction)musicInteracted:(id)sender
{
if (sender == self.playButton)
{
self.pauseButton.enabled = YES;
self.pauseButton.alpha = 1.0f;
self.playButton.enabled = NO;
self.playButton.alpha = 0.3f;
[self.radioControl playRadio];
}
else
{
self.pauseButton.enabled = NO;
self.pauseButton.alpha = 0.3f;
self.playButton.enabled = YES;
self.playButton.alpha = 1.0f;
[self.radioControl pauseRadio];
}
}
-(void)remoteControlReceivedWithEvent:(UIEvent *)event
{
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause:
//[streamer pause];
break;
case UIEventSubtypeRemoteControlPlay:
//[streamer start];
break;
case UIEventSubtypeRemoteControlPause:
//[streamer pause];
break;
case UIEventSubtypeRemoteControlStop:
//[streamer stop];
break;
default:
break;
}
}
@end
最佳答案
感谢@Onur Şahindur,经过几年的努力,我终于有了这个工作。不敢相信这在任何地方都没有记录。正如 Onur 所说,在 stackoverflow 上我们中有很多人都为此苦苦挣扎,但这是第一个真正有效的解决方案。
我还使用“MPRemoteCommandCenter”类进行了此操作。我通过对管理我的 AVPlayer 的单例的方法调用在 appDelegate 中实现了所有内容。这是我的解决方案:
_audioSession = [AVAudioSession sharedInstance];
// Previously, I used [_audioSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&setCategoryError];
// As noted by @Onur, it has to be the following (without options)
[_audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
// Apple documentation says you don't need the following if you are using
// the MPRemoteCommandCenter, but that is not true. It is needed.
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[commandCenter.togglePlayPauseCommand setEnabled:YES];
[commandCenter.playCommand setEnabled:YES];
[commandCenter.pauseCommand setEnabled:YES];
[commandCenter.nextTrackCommand setEnabled:YES];
[commandCenter.previousTrackCommand setEnabled:YES];
[commandCenter.togglePlayPauseCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[[MediaController sharedInstance] playOrPauseMusic]; // Begin playing the current track.
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.playCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[[MediaController sharedInstance] playOrPauseMusic]; // Begin playing the current track.
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.pauseCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[[MediaController sharedInstance] playOrPauseMusic]; // Begin playing the current track.
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.nextTrackCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[[MediaController sharedInstance] fastForward]; // forward to next track.
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.previousTrackCommand addTargetWithHandler: ^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
[[MediaController sharedInstance] rewind]; // back to previous track.
return MPRemoteCommandHandlerStatusSuccess;
}];
[commandCenter.stopCommand setEnabled:NO];
[commandCenter.skipForwardCommand setEnabled:NO];
[commandCenter.skipBackwardCommand setEnabled:NO];
[commandCenter.enableLanguageOptionCommand setEnabled:NO];
[commandCenter.disableLanguageOptionCommand setEnabled:NO];
[commandCenter.changeRepeatModeCommand setEnabled:NO];
[commandCenter.changePlaybackRateCommand setEnabled:NO];
[commandCenter.changeShuffleModeCommand setEnabled:NO];
// Seek Commands
[commandCenter.seekForwardCommand setEnabled:NO];
[commandCenter.seekBackwardCommand setEnabled:NO];
[commandCenter.changePlaybackPositionCommand setEnabled:NO];
// Rating Command
[commandCenter.ratingCommand setEnabled:NO];
// Feedback Commands
// These are generalized to three distinct actions. Your application can provide
// additional context about these actions with the localizedTitle property in
// MPFeedbackCommand.
[commandCenter.likeCommand setEnabled:NO];
[commandCenter.dislikeCommand setEnabled:NO];
[commandCenter.bookmarkCommand setEnabled:NO];
除了上述内容(我将其放入 appDelegate - application:didFinishLaunchingWithOptions)之外,还将其添加到您的 appDelegate 中:
- (BOOL) canBecomeFirstResponder
{
return YES;
}
然后,每次您更改要播放的媒体项目时,我都会从我的媒体 Controller 单例中执行以下代码:
ipodControlArtwork = [[MPMediaItemArtwork alloc]initWithImage:artworkImage];
if (artworkImage != nil && nowPlayingArtist != nil && nowPlayingTitle != nil && ipodControlArtwork != nil) {
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
nowPlayingTitle, MPMediaItemPropertyTitle,
nowPlayingArtist, MPMediaItemPropertyArtist,
ipodControlArtwork, MPMediaItemPropertyArtwork,
[NSNumber numberWithDouble:0.0], MPNowPlayingInfoPropertyPlaybackRate, nil];
}
关于ios - 在 iOS 7 和 8 中通过 AVPlayer 使用远程控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29332001/
嘿。 我在使用 Selenium Remote control 运行 selenium 测试时遇到问题。 打开控制台窗口并键入以下命令后: java -jar selenium-server-stan
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 10 个月前关闭。 Improve this
在 reveal.js Github 中,有一种方法可以使用触摸设备激活演示文稿的远程控制,而无需使用第三方脚本。 这是: Reveal.initialize({ dependencies:
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 5 年前。 Improve this ques
我每天 24 小时在专用机器上运行 VB.NET 应用程序。我希望能够接收状态更新并远程控制/调试应用程序(即通过互联网从另一台计算机)。 如果通信是轻量级的(就发送和接收的字节而言),那将是一个优势
这是一个将在 8 小时内上交的项目!我们被这个问题困扰,并认为这个地方是最后的手段。 我正在尝试使用 Arduino 打开/关闭远程控制 socket 。这样做时我们会遇到不一致的情况。有时,当它进入
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this q
我想在我的房间手册中远程控制 socket ,而无需在我的树莓派上安装额外的库。我想在 C 中使用 UART 接口(interface)。 socket 有 433 Mhz 接收器,我使用 433 M
我正在尝试从 C# 控制 VLC 媒体播放器。我尝试使用 .Net 中的 FindWindow() 命令获取窗口句柄,但我发现每次播放文件时窗口名称都会更改。我遇到的最大问题是将 wm_command
我一直很高兴地将 XPath 与 Selenium 一起使用,甚至将 getEval 与 Javascript 一起使用,但一位同事说,如果能够在 Selenium 中使用 JQuery 选择器不是很
过去,Netscape 有一项功能,允许您从命令行远程控制浏览器 session (使用“-remote”标志)。我正在寻找类似的功能,但在现代浏览器中。 Mplayer 的 slave mode 是
我正在尝试控制安装在远程计算机上的 Windows 服务。我正在使用 ServiceController 类。 我有这个: ServiceController svc = new ServiceCo
这是我第一次在这里发帖。 我正在做一个项目,我想通过不同的输入模式(例如多点触控、3D 鼠标...)来控制 Windows Media Player。目前,我正试图找到一种远程控制 Windows M
我们在屏蔽箱里用手机做实验。 无法进行无线/ radio 通信,因此我们需要使用 USB 电缆。 “androidscreencast”非常适合通过 USB 远程控制 android 设备。 现在有必
启用 WinRM 远程服务: winrm quickconfig 查看 WinRM 服务监听状态: winrm e winrm/config/listener
我正在寻找一个 Emacs (& Chrome) 包,它可以 每个应用程序之间的通信——尤其是从 Emacs 远程控制 Chrome,类似于 Mozrepl对于火狐。 我找到了一个名为 skewer-
Selenium Remote Control 有一个“get_html_source”方法,它以字符串形式返回当前页面的源。 据我所知,此方法适用于 Firefox 和 Safari 中的所有情况。
我需要创建某种可以与 UPnP 媒体服务器交互的 Remote 。 我读到过 UPnP AV 堆栈有类似三种应用程序:媒体服务器、媒体渲染器和控制点。起初,我认为控制点是我想要编程的,但是,在浏览了几
我正在尝试找到一种工具来从 Windows 7 机器远程控制运行 Windows CE 6.0 的摩托罗拉 MC3190 设备。 我已经将 Mymobiler 与 Intermec CN3 设备一起使
我是一名优秀的程序员,十分优秀!