2014-11-18 14 views
5

Ho un'applicazione che riproduce l'audio in background. Sto cercando di correggere un bug in cui i controlli audio (riproduzione/pausa), sulla schermata principale (ecc.), NON funzionano su iOS 8.0+ ma funzionano FINE su iOS 7.0. Sto scavando cercando di capire quale sia il problema e stavo uscendo vuoto. Qualsiasi idea sarebbe molto apprezzata. Ecco cosa ho in atto.remoteControlReceivedWithEvent chiamato su dispositivo iOS 7.0 ma non iOS 8.0

Nelle impostazioni di progetto: Ho assicurato che UIBackgroundModes è impostato su audio.

Nella AppDelegate.h: Ho un membro della AVAudioSession* session; nonche la AVPlayer *audioPlayer;

Nella AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ 

self.session = [AVAudioSession sharedInstance]; 

NSError* error = NULL; 
[self.session setCategory:AVAudioSessionCategoryPlayback error:&error]; 
[self.session setActive:YES error:&error]; 

if (error) { 
    NSLog(@"AVAudioSession error: %@", [error localizedDescription]); 
} 

Nel AudioPlayerViewController.m

- (void)viewDidLoad { 

//Get the Audio 
NSURL *url = [NSURL URLWithString:self.audioUrl]; 
AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; 

//Setup the player 
self.playerItem = [AVPlayerItem playerItemWithAsset:asset]; 
appDelegate.audioPlayer = [AVPlayer playerWithPlayerItem:self.playerItem]; 

//Setup the "Now Playing" 
NSMutableDictionary *mediaInfo = [[NSMutableDictionary alloc]init]; 
[mediaInfo setObject:self.title forKey:MPMediaItemPropertyTitle]; 
[mediaInfo setObject:self.artist forKey:MPMediaItemPropertyArtist]; 
[mediaInfo setObject:self.album forKey:MPMediaItemPropertyAlbumTitle]; 
[mediaInfo setObject:[NSNumber numberWithDouble:duration ] forKey:MPMediaItemPropertyPlaybackDuration]; 
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:mediaInfo]; 

}

// Process remote control events 
- (void) remoteControlReceivedWithEvent:(UIEvent *)event { 

NSLog(@"AudioPlayerViewController ... remoteControlReceivedWithEvent top ....subtype: %d", event.subtype); 

if (event.type == UIEventTypeRemoteControl) { 

    switch (event.subtype) { 
     case UIEventSubtypeRemoteControlTogglePlayPause: 
      [self togglePlayPause]; 
      break; 
     case UIEventSubtypeRemoteControlPause: 
      [self doPause]; 
      break; 
     case UIEventSubtypeRemoteControlStop: 
      [self doPause]; 
      break; 
     case UIEventSubtypeRemoteControlPlay: 
      [self doPlay]; 
      break; 
     case UIEventSubtypeRemoteControlPreviousTrack: 
      [self nextOrPrevTrack]; 
      break; 
     case UIEventSubtypeRemoteControlNextTrack: 
      [self nextOrPrevTrack]; 
      break; 
     default: 
      break; 
    } 
} 

}

-(void)viewDidAppear:(BOOL)animated { 
[super viewDidAppear:animated]; 
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
[self becomeFirstResponder]; 

}

- (void)viewWillDisappear:(BOOL)animated { 
[super viewWillDisappear:animated]; 
[[UIApplication sharedApplication] endReceivingRemoteControlEvents]; 
[self resignFirstResponder]; 

}

- (BOOL) canBecomeFirstResponder { 
return YES; 

}

risposta

8

finalmente capito il problema che stavo avendo. Alla fine sembrava che gli eventi dal telecomando nella schermata iniziale non fossero mai stati inseriti nella mia app e fino ai miei controller di visualizzazione. Ho finito con la sottoclasse dello UIWindow in modo da poter vedere quali eventi si stavano facendo strada attraverso la catena. Come UIWindow è un UIResponder Ho anche aggiunto il - (void)remoteControlReceivedWithEvent:(UIEvent *)event alla sottoclasse. Poi nel makeKeyAndVisible ho aggiunto il:

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
[self becomeFirstResponder]; 

ho iniziato il debugger e il -(void)makeKeyAndVisible è mai stato chiamato! Ho quindi cercato il mio delegato dell'app per la variabile membro window e la riga [window makeKeyAndVisible]; non si trovava da nessuna parte! L'ho aggiunto di nuovo (come avrebbe dovuto essere lì) e presto gli eventi si stanno indirizzando verso le posizioni corrette come per magia. Perché questo stava lavorando su alcune versioni di iOS e non su altri e senza altri problemi evidenti è oltre me.

Spero che questo aiuti qualcuno in futuro.

+0

puoi pubblicare un codice relativo a come hai fatto funziona? Ti piace come e dove hai fatto la sottoclasse di UIWindow'? – NorthBlast

+0

Il problema era la chiamata mancante [window makeKeyAndVisible]. Non ha nulla a che fare con la sottoclasse della classe UIWindow. – Caleb

4

Nella tua ViewController aggiungere

override func viewWillAppear(animated: Bool) { 
     super.viewWillAppear(animated) 

     UIApplication.sharedApplication().beginReceivingRemoteControlEvents() 
     self.becomeFirstResponder() 
} 

override func remoteControlReceivedWithEvent(event: UIEvent) { 
     // your stuff 
    } 

In AppDelegate aggiungere

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 

var error: NSError? 
     AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error) 
     AVAudioSession.sharedInstance().setActive(true, error: &error) 
} 

SWIFT 3

UIApplication.shared.beginReceivingRemoteControlEvents() 
self.becomeFirstResponder() 

do { 
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) 
    try AVAudioSession.sharedInstance().setActive(true) 
} catch { 
    print("hmmm...") 
} 
+0

Cosa succede quando si hanno più ViewController di cui si è Player e si passa a un altro ViewController. Come continui a gestire i telecomandi nel PlayerController che è ora "distrutto"? – justdan0227

+0

Buon punto: penso che dovresti gestire tale comportamento nel tuo AppDelegate o in un oggetto Singleton –

+0

Questa è la risposta corretta. aggiunto AppDelegate logico per chiamare i metodi nel controller della vista poiché i giocatori sono statici. – justdan0227

Problemi correlati