iPhone App:不恢复 AVAudio Player 中的音频会话
Posted
技术标签:
【中文标题】iPhone App:不恢复 AVAudio Player 中的音频会话【英文标题】:iPhone App: not resuming audio session in AVAudio Player 【发布时间】:2011-09-29 07:33:39 【问题描述】:在我的 iPhone 应用程序中,我正在使用 AVAudioPlayer 播放音乐。当我的应用程序在后台运行时,它也在运行时我写了这段代码
在 AppDelegate 上 -- 应用程序 didFinishLaunchingWithOptions
audioManager= [[AudioManager alloc] init];
audioManager.delegate=self;
audioManager.soundFile=[[[NSBundle mainBundle] pathForResource:@"mysong" ofType:@"wav"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[audioManager setFileForPlay];
[audioManager.player setNumberOfLoops:-1];
[audioManager.player setVolume:.5];
[audioManager play];
-(void) playerBeginInterruption:(AVAudioPlayer *)p
[usdef setValue:@"START" forKey:@"LOCATIONMANAGER"];
[locationManager startUpdatingLocation];
[p pause];
// audioManager=nil;
-(void) playerBeginInterruptionInBackground:(AVAudioPlayer *)p
[usdef setValue:@"START" forKey:@"LOCATIONMANAGER"];
[locationManager startUpdatingLocation];
[p pause];
//audioManager=nil;
-(void) playerEndInterruption:(AVAudioPlayer *)p
NSLog(@"Inteerpt END");
[p prepareToPlay];
[p play];
[usdef setValue:@"STOP" forKey:@"LOCATIONMANAGER"];
-(void) playerEndInterruptionInBackgroud:(AVAudioPlayer *)p
NSLog(@"Inteerpt END BG");
// [self performSelector:@selector(allocaudioManager)];
[p prepareToPlay];
[p play];
[usdef setValue:@"STOP" forKey:@"LOCATIONMANAGER"];
// [locationManager stopUpdatingLocation];
现在我已经为处理委托方法的音频管理器创建了单独的类
在.h文件中
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
@protocol AudioManagerDelegate;
@interface AudioManager : NSObject <AVAudioPlayerDelegate>
AVAudioPlayer *player;
NSString *soundFile;
BOOL inBackground;
id<AudioManagerDelegate> delegate;
@property (nonatomic, assign) id<AudioManagerDelegate>delegate;
@property (nonatomic, retain) NSString *soundFile;
@property (nonatomic, assign) AVAudioPlayer *player;
@property (nonatomic, assign) BOOL inBackground;
- (void)play;
- (void)pause;
- (void)stop;
- (void)registerForBackgroundNotifications;
-( void) setFileForPlay;
@end
@protocol AudioManagerDelegate <NSObject>
@optional
- (void)playerDidFinishPlayingInBackground:(AVAudioPlayer*)p;
- (void)playerDidFinishPlaying:(AVAudioPlayer*)p;
- (void)playerBeginInterruption:(AVAudioPlayer*)p;
- (void)playerBeginInterruptionInBackground:(AVAudioPlayer*)p;
- (void)playerEndInterruption:(AVAudioPlayer *)p;
- (void)playerEndInterruptionInBackgroud:(AVAudioPlayer *)p;
@end
在 .m 文件中
@implementation AudioManager
@synthesize delegate;
@synthesize player;
@synthesize inBackground;
@synthesize soundFile;
void RouteChangeListener(void *inClientData, AudiosessionPropertyID inID,UInt32 inDataSize, const void *inData);
-(id) init
if((self=[super init]))
OSStatus result = AudioSessionInitialize(NULL, NULL, NULL, NULL);
if (result)
NSLog(@"Error initializing audio session! %ld", result);
[[AVAudioSession sharedInstance] setDelegate: self];
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
if (setCategoryError)
NSLog(@"Error setting category! %@", setCategoryError);
result = AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, RouteChangeListener, self);
if (result)
NSLog(@"Could not add property listener! %ld", result);
return self;
return nil;
-(void) setFileForPlay
self.player=nil;
player = [[AVAudioPlayer alloc] initWithData:[NSData dataWithContentsOfFile:self.soundFile] error:nil];//initWithContentsOfURL:[NSURL URLWithString:self.soundFile] error:nil];
if (self.player)
player.delegate = self;
-(void) play
[self.player play];
-(void)pause
[self.player pause];
NSLog(@"in Pause");
-(void)stop
[self.player stop];
NSLog(@"in stop");
void RouteChangeListener(void *inClientData, AudioSessionPropertyID inID,UInt32 inDataSize, const void *inData)
AudioManager* This = (AudioManager*)inClientData;
if (inID == kAudioSessionProperty_AudioRouteChange)
CFDictionaryRef routeDict = (CFDictionaryRef)inData;
NSNumber* reasonValue = (NSNumber*)CFDictionaryGetValue(routeDict, CFSTR(kAudioSession_AudioRouteChangeKey_Reason));
int reason = [reasonValue intValue];
if (reason == kAudioSessionRouteChangeReason_OldDeviceUnavailable)
[This stop];
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)p successfully:(BOOL)flag
if (flag == NO)
NSLog(@"Playback finished unsuccessfully");
[p setCurrentTime:0.];
if (inBackground)
[delegate playerDidFinishPlayingInBackground:p];
else
[delegate playerDidFinishPlaying:p];
- (void)playerDecodeErrorDidOccur:(AVAudioPlayer *)p error:(NSError *)error
NSLog(@"ERROR IN DECODE: %@\n", error);
// we will only get these notifications if playback was interrupted
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)p
NSLog(@"Interruption begin ");
// the object has already been paused, we just need to update UI
if (inBackground)
[delegate playerBeginInterruptionInBackground:p];
else
[delegate playerBeginInterruption:p];
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)p withFlags:(NSUInteger)flags
if(inBackground)
[delegate playerEndInterruptionInBackgroud:p];
else
[delegate playerEndInterruption:p];
NSLog(@"Interruption ended. Resuming playback");
- (void)registerForBackgroundNotifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(setInBackgroundFlag)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(clearInBackgroundFlag)
name:UIApplicationWillEnterForegroundNotification
object:nil];
- (void)setInBackgroundFlag
inBackground = true;
- (void)clearInBackgroundFlag
inBackground = false;
@end
现在的问题是,如果我从 ipod 库播放任何歌曲并停止歌曲并关闭 ipod 库,我在启动 ipos 库之前正在播放的原始 avaudioplayer 没有恢复意味着它不再是播放歌曲
可能出了什么问题?
是否有任何演示项目或示例代码可以帮助我?
请帮助和建议。
【问题讨论】:
你是说在你的应用程序中,你有一个 AVAudioPlayer 播放一些添加到你的项目中的音乐文件。那么当你离开应用打开ipod播放器播放歌曲,然后重新打开你的应用时,它并没有恢复原来的歌曲,而是你的ipod库的歌曲? 不,它不是来自 ipod 库,它是我已经包含在我的项目中的音频文件 在这种情况下,我一直在您的应用程序委托中使用方法 applicationWillResignActive 和 applicationDidBecomeActive 来暂停和启动您的 AVAudioPlayer。 在我的情况下,它应该在 audioPlayerEndInterruption 上重新开始,那时我的应用程序将仅在后台模式下运行 【参考方案1】:您不必在audioPlayerBeginInterruption:
中的AVAudioPlayer
(代码中的p
)上调用pause
,由于中断,播放器不应在该阶段播放。在audioPlayerEndInterruption:
中,以下内容通常对我有用:
[p prepareToPlay];
[p play];
iOS 文档中的 Audio Session Cookbook 有一个关于“使用 AVAudioPlayer 类处理中断”的部分也应该有所帮助。
【讨论】:
以上是关于iPhone App:不恢复 AVAudio Player 中的音频会话的主要内容,如果未能解决你的问题,请参考以下文章