cod*_*kie 24 objective-c core-audio avaudioplayer avplayer ios7
我在Google和StackOverflow上做了很多研究.我发现的所有答案在iOS 7中都不起作用.我开始在iOS 7 SDK中使用Xcode 5编写新的应用程序.
我所要做的就是从应用程序包中存储的文件(而不是音乐库)中播放应用程序中的音频.我希望在后台播放音频并在屏幕锁定时控制(除控制中心外).
我将APPNAME-Info.plist密钥设置UIBackgroundModes为音频.它不处理app委托中的内容; 一切都在ViewController中完成
@interface ViewController : UIViewController <AVAudioPlayerDelegate>
Run Code Online (Sandbox Code Playgroud)
在实现的viewDidAppear:方法中,我调用super,然后是以下代码:
// Once the view has loaded then we can register to begin receiving controls and we can become the first responder
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
Run Code Online (Sandbox Code Playgroud)
在我的实现viewWillDisappear:方法中,我有以下代码:
// End receiving events
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
Run Code Online (Sandbox Code Playgroud)
我还实现了canBecomeFirstResponder方法,返回YES.接下来,我实现了该remoteControlReceivedWithEvent:方法:
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
// If it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay) {
[self playPauseAudio:self];
} else if (event.subtype == UIEventSubtypeRemoteControlPause) {
[self playPauseAudio:self];
} else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
[self playPauseAudio:self];
}
}
}
Run Code Online (Sandbox Code Playgroud)
让我感到困惑的是,这个完全相同的设置在iOS 6上运行良好.在iOS 7上,它不起作用.它曾经在iOS 6中如此简单.在iOS 7 SDK中有些根本改变了.我错过了什么?
cod*_*kie 16
我设法解决了这个问题,并且为了挽救另一个可怜的灵魂的头发而去:
首先确保您的Info.plist正确地将音频列为后台模式.
(如果你不知道我在说什么,请选择YOURAPPNAME-Info.plist选择它.单击加号并添加一个新的密钥UIBackgroundModes并展开它.添加一个名为audio.的值.)
您需要引用任何正在创建音频的播放对象.由于我只播放音频并且AV播放器不遵守背景音频,请在视图控制器的标题中使用它:
@property (nonatomic, retain) MPMoviePlayerController *audioPlayer;
Run Code Online (Sandbox Code Playgroud)
在实施中,执行以下操作:
[super viewDidAppear:animated];
//Once the view has loaded then we can register to begin recieving controls and we can become the first responder
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
Run Code Online (Sandbox Code Playgroud)
和
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//End recieving events
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
Run Code Online (Sandbox Code Playgroud)
添加两个方法
//Make sure we can recieve remote control events
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void) registerForAudioObjectNotifications {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver: self
selector: @selector (handlePlaybackStateChanged:)
name: MixerHostAudioObjectPlaybackStateDidChangeNotification
object: audioObject];
}
Run Code Online (Sandbox Code Playgroud)
现在所有重要代码 - 这使您的应用程序可以控制来自"控制中心"和锁定屏幕的音频:
- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause:
[self playOrStop: nil];
break;
default:
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处添加许多类型的事件类型并调用任何方法.
典型事件是:
UIEventSubtypeRemoteControlPlay = 100, //Parent EVENT
// All below are sub events and you can catch them using switch or If /else.
UIEventSubtypeRemoteControlPause = 101,
UIEventSubtypeRemoteControlStop = 102,
UIEventSubtypeRemoteControlTogglePlayPause = 103,
UIEventSubtypeRemoteControlNextTrack = 104,
UIEventSubtypeRemoteControlPreviousTrack = 105,
UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
UIEventSubtypeRemoteControlEndSeekingBackward = 107,
UIEventSubtypeRemoteControlBeginSeekingForward = 108,
UIEventSubtypeRemoteControlEndSeekingForward = 109,
Run Code Online (Sandbox Code Playgroud)
要调试帮助,您可以使用:
MPMoviePlayerController *mp1= (MPMoviePlayerController *)[notification object];
NSLog(@"Movie State is: %d",[mp1 playbackState]);
switch ([mp1 playbackState]) {
case 0:
NSLog(@"******* video has stopped");
break;
case 1:
NSLog(@"******* video is playing after being paused or moved.");
break;
case 2:
NSLog(@"******* video is paused");
break;
case 3:
NSLog(@"******* video was interrupted");
break;
case 4:
NSLog(@"******* video is seeking forward");
break;
case 5:
NSLog(@"******* video is seeking Backwards");
break;
default:
break;
Run Code Online (Sandbox Code Playgroud)
这就是它 - 希望它有助于那里的一些人! - 这在带有Storyboard应用程序的iOS 7和iOS 6以及使用耳机和所有新控制中心的控制方面都非常完美.
小智 7
显然问题出在Apple的一边,因为iOS更新7.0.3解决了这个问题.除了Alex关于UIEventSubtype更改的内容之外,iOS6上运行的代码现在可以在iOS7上运行.
为了完整起见,这是我在iOS6和iOS7中使用的相关代码 - 在udpate到7.0.3之后.还包括项目构建阶段中的AVFoundation.framework和MediaPlayer.framework - >使用库链接二进制文件.在app delegate中没有此代码.
在viewcontroller .h文件中:
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
@interface NewsDetailViewController : UIViewController <UIWebViewDelegate, AVAudioSessionDelegate>
@property (nonatomic) MPMoviePlayerController *audioPlayer;
Run Code Online (Sandbox Code Playgroud)
在viewcontroller .m文件中:
- (void)viewDidLoad
{
[super viewDidLoad];
self.audioPlayer = [[MPMoviePlayerController alloc] initWithContentURL:audioUrl];
[self.audioPlayer prepareToPlay];
[self.audioPlayer.view setFrame:CGRectMake(0, 0, self.audioView.frame.size.width, 42)];
self.audioPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.audioView addSubview:self.audioPlayer.view];
[self.audioPlayer play];
NSError *setCategoryError = nil;
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&activationError];
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.audioPlayer stop];
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlPlay:
[self.audioPlayer play];
break;
case UIEventSubtypeRemoteControlPause:
[self.audioPlayer pause];
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
if (self.audioPlayer.playbackState == MPMoviePlaybackStatePlaying) {
[self.audioPlayer pause];
}
else {
[self.audioPlayer play];
}
break;
default:
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想在iphone和模拟器中播放背景音频,那么你需要在plist中编写这段代码.首先确保你的Info.plist正确地将音频列为背景模式.
(如果你不知道我在说什么,请选择YOURAPPNAME-Info.plist选择它.点击加号并键入一个键UIBackgroundModes并输入.添加一个名为"App播放音频"的值(用于模拟器)或"应用程序播放"音频或流音频/视频使用AirPlay"(适用于iPhone).)

在AppDelegate.m中
- (void)applicationDidEnterBackground:(UIApplication *)application
{
__block UIBackgroundTaskIdentifier task = 0;
task=[application beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Expiration handler called %f",[application backgroundTimeRemaining]);
[application endBackgroundTask:task];
task=UIBackgroundTaskInvalid;
}];
}
Run Code Online (Sandbox Code Playgroud)
在项目中添加这两个框架,在ViewController.h中添加一些代码
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
@interface ViewController : UIViewController <UIWebViewDelegate, AVAudioSessionDelegate>
@property (nonatomic) MPMoviePlayerController *audioPlayer;
Run Code Online (Sandbox Code Playgroud)
提醒您应该在项目中添加这些框架引用.
然后在Viewcontrller.m中
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.audioPlayer stop];
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURL *audioUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"songName" ofType:@"mp3"]];
self.audioPlayer = [[MPMoviePlayerController alloc] initWithContentURL:audioUrl];
[self.audioPlayer prepareToPlay];
[self.audioPlayer.view setFrame:CGRectMake(0, 0, self.view.frame.size.width-100, 42)];
self.audioPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.audioPlayer.view];
[self.audioPlayer play];
// for run application in background
NSError *setCategoryError = nil;
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&activationError];
[[AVAudioSession sharedInstance] setDelegate:self];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
}
Run Code Online (Sandbox Code Playgroud)
我希望它能帮助你在iphone和模拟器中播放背景音频.