Приложение для iPhone: не возобновление аудиосеанса в AVAudio Player - PullRequest
4 голосов
/ 29 сентября 2011

В моем приложении для 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, мой исходный проигрыватель avaudioplayer, который воспроизводился до запуска библиотеки ipos, не возобновляет работу, значит, она не воспроизводит песню снова

что может быть не так?

Есть ли какой-нибудь демонстрационный проект или пример кода, который может мне помочь?

Пожалуйста, помогите и предложите.

1 Ответ

4 голосов
/ 08 октября 2011

Вам не нужно звонить pause на AVAudioPlayer (p в вашем коде) в audioPlayerBeginInterruption:, игрок не должен играть на этом этапе из-за прерывания. В audioPlayerEndInterruption: у меня обычно работает следующее:

[p prepareToPlay];
[p play];

Поваренная книга аудиосеанса в документах iOS содержит раздел «Обработка прерываний с помощью класса AVAudioPlayer», который также должен помочь.

...