2010-08-11 15 views
31

Aktualnie próbuję skonfigurować dźwięk w tle dla aplikacji rozwijanej na iOS 4. Aplikacja nie ma dedykowanego odtwarzacza muzycznego viewController, jednak w przeciwieństwie do innych dźwięków w tle aplikacje takie jak Pandora, co sprawia, że ​​zadanie jest nieco bardziej zagmatwane.iOS 4: Zdalne sterowanie dźwiękiem w tle

Ustawiłem odpowiednie ustawienia Info.plist poprawnie i posiadam obiekt AVAudioPlayer w aplikacji delegat, który jest dostępny zewsząd. Kiedy użytkownik odtwarza utwór, zastępuję AVAudioPlayer nowym, zainicjowanym z utworem i odtwarza go. To wszystko działa świetnie, z tym że teraz nie mam pojęcia, jak uzyskać wsparcie dla zdarzeń zdalnego sterowania.

podstawie dokumentacji Apple, mam to:

- (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; 
} 

- (void)remoteControlReceivedWithEvent:(UIEvent *)event { 
    switch(event.subtype) { 
     case UIEventSubtypeRemoteControlTogglePlayPause: 
      if([iPhoneAppDelegate backgroundAudioPlayer].playing) 
       [iPhoneAppDelegate pauseBackgroundAudioPlayer]; 
      else 
       [iPhoneAppDelegate playBackgroundAudioPlayer]; 
      break; 
    } 
} 

Chodzi o to, gdzie mogę umieścić to? Dokumentacja Apple wydaje się sugerować, że powinno to być gdzieś w jakimś kontrolerze widoku, ale moja aplikacja ma wiele kontrolerów widoku i kontrolerów nawigacyjnych. Gdziekolwiek spróbuję to zrobić, z jakiegoś powodu dotknięcie przycisku Przełącz/Odtwórz w wielozadaniowych pilotach zdalnego sterowania powoduje, że utwór po prostu zatrzymuje się na chwilę, a następnie wznawia, lub w jakiś sposób powoduje dwukrotne odtworzenie piosenki.

+0

Jak zmieniłeś przycisk odtwarzania/zatrzymania na pasku wielozadaniowym ?! –

Odpowiedz

19

Znalazłem kilka rozwiązań do odbierania globalnych zdarzeń zdalnego sterowania na forach programistów Apple po odrobinie wyszukiwania.

Jednym ze sposobów jest podklasa UIWindow i zastąpienie jej remoteControlReceivedWithEvent:.

Drugi, być może ładniejszy sposób to podklasa UIApplication i zastąpienie sendEvent:. W ten sposób możesz przechwycić wszystkie zdarzenia zdalnego sterowania i obsługiwać je globalnie, a żaden inny responder nie poradzi sobie z nimi później w łańcuchu respondentów.

- (void)sendEvent:(UIEvent *)event { 
    if (event.type == UIEventTypeRemoteControl) { 
      // Handle event 
    } 
    else 
      [super sendEvent:event]; 
} 
+2

Zobacz mój komentarz do odpowiedzi Briana Dam Pedersena – HiveHicks

+0

Jeszcze ładniejszym sposobem na to jest dodanie go do zwykłego UIApplication w kategorii – hypercrypt

+0

Polecam odpowiedź Briana – Mazyod

4

Druga metoda nie działa dla mnie, sendEvent nigdy nie była wywoływana. Jednak pierwsza metoda działała ładnie (podklasy UIWindow).

+0

Działa jak urok. Chcę dodać, że beginReceivingRemoteControlEvents można wywołać wewnątrz delegata aplikacji, aby zasubskrybować zdarzenie zdalnego sterowania. – Andy

0

Nie ma potrzeby tworzenia podklasy Window lub forward. Wystarczy poradzić sobie z głównym kontrolerem widoku. Zobacz przykład Audio Mixer (MixerHost).

http://developer.apple.com/LIBRARY/IOS/#samplecode/MixerHost/Listings/Classes_MixerHostViewController_m.html

+2

Chodzi o to, że główny kontroler widoku nie zawsze będzie wyświetlany na ekranie, gdy aplikacja znajdzie się w tle, tzn. Nie stanie się pierwszą odpowiedzią, jeśli modalny jest na ekranie. – pablasso

+0

@pablasso może być, w zależności od aplikacji. Ale nie we wszystkich przypadkach, zgadzam się z tym. – slf

37

przykłady dokumentacji są nieco mylące, ale nie ma potrzeby do podklasy czegokolwiek gdziekolwiek. Prawidłowe miejsce do umieszczenia remoteControlReceivedWithEvent: jest w delegacie aplikacji, ponieważ pozostaje w łańcuchu respondenta, niezależnie od tego, czy aplikacja jest na pierwszym planie, czy nie. Również zdarzenia zdalnego sterowania na początku/końcu powinny być oparte na tym, czy faktycznie potrzebujesz zdarzeń, a nie na widoczności jakiegoś losowego widoku.

+11

Całkowicie poprawne. Aby uzyskać pełną kontrolę nad zdalną kontrolą aplikacji (czy to na pierwszym planie, czy w tle), musisz zadzwonić do beginReceivingRemoteControlEvents w aplikacji: didFinishLaunchingWithOptions :, ale to nie wszystko. Twoja aplikacja UIApplicationDelegate zacznie otrzymywać zdarzenia zdalnej kontroli po tym, jak aplikacja poinformuje iOS, że odtwarza utwór - ustawiając właściwość MPNowPlayingInfoCenter terazPlayingInfo. – HiveHicks

+0

To naprawdę świetna odpowiedź, utknąłem z tygodnia. –

+0

Umieszczanie remoteControlReceivedWithEvent: w delegata aplikacji nie działa dla mnie; Musiałem przejść z podklasowaniem UIWindow. – JosephH

3

Walczyłem z tym przez chwilę i żadna z powyższych odpowiedzi nie zadziałała. Błąd w moim kodzie, i mam nadzieję, że to pomoże komuś, kto to czyta, był taki, że miałem zestaw AudioSession, aby mieszać się z innymi. Chcesz być pierwszoplanowym odtwarzaczem audio, aby uzyskać zdalne sterowanie. Sprawdź, czy masz błędny kod tak:

[[AVAudioSession sharedInstance] setDelegate: self]; 
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil]; 
    UInt32 doSetProperty = 0; 
    AudioSessionSetProperty (
          kAudioSessionProperty_OverrideCategoryMixWithOthers, 
          sizeof (doSetProperty), 
          &doSetProperty 
          ); 
    NSError *activationError = nil; 
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError];  

i wyjąć AudioSessionSetProperty lub zmienić doSetProperty do 1.

0

Jedną z rzeczy, które wydają się mieć wpływ na to zachowanie, są wszelkie opcje kategorii ustawione dla AVAudioSession przy użyciu setCategory: withOptions: error: zamiast tylko setCategory: error :. W szczególności, z prób i błędów, wydaje się, że jeśli ustawisz AVAudioSessionCategoryOptionMixWithInne, nie otrzymasz zdalnych zdarzeń kontrolnych; kontrolki odtwarzane teraz będą nadal kontrolować aplikację dla iPoda. Jeśli ustawisz AVAudioSessionCategoryOptionDuckOthers, otrzymasz zdalne sterowanie zdarzeniami, ale wydaje się, że mogą występować niejasności co do tego, która aplikacja jest kontrolowana. Ustawienie kategoriiOpcje na 0 lub po prostu wywołanie setCategory: błąd: działa najlepiej.