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 中的音频会话的主要内容,如果未能解决你的问题,请参考以下文章

我的Iphone4越狱过 但是越狱的图标不见了 怎么办

iphone快速加载声音文件

SKScene 中的 AVAudio 播放器出错

使用 AVAudio 循环播放 mp3

致命错误:使用 AVAudio 展开可选值时意外发现 nil

在应用程序终止之前获取 AVAudio 录音 URL