2014-11-18 8 views
5

Mam aplikację, która odtwarza dźwięk w tle. Próbuję naprawić błąd, w którym elementy sterowania dźwiękiem (odtwarzanie/pauza) na ekranie głównym (itp.) NIE DZIAŁAJĄ w systemie iOS 8.0+, ale działają w trybie FINE na iOS 7.0. Przekopuję się, próbując dojść do tego, o czym jest problem, i doszedłem do pustki. Wszelkie pomysły będą mile widziane. Oto, co mam na miejscu.remoteControlReceivedWithEvent wywołane na urządzeniu z iOS 7.0, ale nie iOS 8.0

W Ustawieniach projektu: Upewniłem się, że UIBackgroundModes jest ustawione na audio.

W AppDelegate.h: Mam członka na AVAudioSession* session; jak również AVPlayer *audioPlayer;

W 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]); 
} 

W 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; 

}

Odpowiedz

8

końcu zorientowali się problem ja mieć. Ostatecznie wydawało się, że zdarzenia z pilota na ekranie głównym nigdy nie pojawiały się w mojej aplikacji i w moich kontrolerach widoku. Zakończyłem podklasy UIWindow, dzięki czemu mogłem zobaczyć, jakie zdarzenia przedostały się przez łańcuch. Jako UIWindow jest UIResponder Dodałem również - (void)remoteControlReceivedWithEvent:(UIEvent *)event do podklasy. Następnie w makeKeyAndVisible I dodaje:

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

zacząłem się debuggera i -(void)makeKeyAndVisible nigdy nazwano! Następnie przeszukałem swojego uczestnika aplikacji pod zmienną składową window, a linii [window makeKeyAndVisible]; nigdzie nie było! Dodałem go z powrotem (tak jak powinno), a wydarzenia presto są kierowane do właściwych miejsc, takich jak magia. Dlaczego to działa na niektóre wersje iOS, a nie inne i bez żadnych innych zauważalnych problemów jest poza mną.

Mam nadzieję, że pomoże to komuś w przyszłości.

+0

można zakładać jakiś odpowiedni kod, w jaki zrobiłeś to działa? Podobnie jak i gdzie zrobiłeś podklasę 'UIWindow'? – NorthBlast

+0

Problem polegał na braku połączenia [window makeKeyAndVisible]. Nie ma to nic wspólnego z podklasowaniem klasy UIWindow. – Caleb

4

W swojej ViewController dodać

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

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

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

W AppDelegate dodać

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

Co się dzieje, gdy masz wiele kontrolerów ViewController, z których jeden jest Player i przełączasz się na inny ViewController. Jak nadal radzisz sobie z pilotami w kontrolerze PlayerController, który jest teraz "zniszczony"? – justdan0227

+0

Dobra uwaga: Myślę, że nie powinieneś zajmować się takim zachowaniem w AppDelegate lub w Singleton Object –

+0

To jest poprawna odpowiedź. dodano logikę AppDelegate, aby wywołać metody w kontrolce widoku, ponieważ gracze są statyczni. – justdan0227

Powiązane problemy