2012-01-18 11 views
9

Przesyłam muzykę w oddzielnym wątku. Jeśli opuszczę aplikację (onPause(), onStop() dzwonienie, itp.), Muzyka będzie nadal odtwarzana, ale ostatecznie - po otwarciu innych aplikacji i przełączeniu się między nimi i powrocie na ekran główny - moja aplikacja zostanie zabita. Bez awarii, tylko WIN DEATH i process com.myapp.android has died w logcat. Oczywiście, aby system mógł odzyskać zasoby, jego system może zniszczyć aplikacje.MediaPlayer w oddzielnym wątku vs uruchomiony w usłudze via startForeground()

Moje pytanie brzmi: czy uruchamianie rzeczy w wątku poza głównym wątkiem (UI) oznacza, że ​​ma teraz mniejszy priorytet w odniesieniu do systemu? Czy oznacza to, że jest bardziej prawdopodobne, że zostanie zabity, niż gdybym uruchomił odtwarzacz multimedialny w trybie Service, a nawet skorzystał z usługi startForeground(), aby usługa działała na pierwszym planie?

Wszelkie przemyślenia lub wyjaśnienia byłyby mile widziane!

EDIT

Również część dokumentacji o usługach myli mnie. W stosownej części, stwierdza:

Uwaga: Usługa działa w głównym wątku jej hosting procesowej-usługi nie tworzy swój własny wątek i nie działa w oddzielnym procesie (o ile nie określono inaczej). Oznacza to, że jeśli Twoja usługa będzie wykonywała intensywnie pracę z CPU lub blokuje operacje (takie jak odtwarzanie MP3 lub praca w sieci), powinieneś utworzyć nowy wątek w ramach usługi, aby wykonać tę pracę.

Zawsze uruchomiłem odtwarzanie MP3 w usłudze w głównym wątku, a interfejs użytkownika pozostał aktywny. Jeśli mam umieścić go w osobnej nici zgodnie z zaleceniami w powyższym cytacie, to nie będę kończył z powrotem tam, gdzie zacząłem, a mianowicie z odtwarzaniem multimediów poza głównym wątkiem, zwiększając tym samym prawdopodobieństwo, że odtwarzanie jest zabijany, gdy inne aplikacje są otwierane itd.?

Odpowiedz

2

Wydaje mi się, że na większość pytań odpowiada Android documentation on Services.

z linku:

Usługa planie jest usługą, która jest uważana za coś użytkownik jest aktywnie świadomy i dlatego nie kwalifikuje się do systemu zabić kiedy mało pamięci. Usługa pierwszego planu musi dostarczyć powiadomienie dla paska stanu, które jest umieszczone pod nagłówkiem "W toku" , co oznacza, że ​​powiadomienie nie może zostać odrzucone, chyba że usługa zostanie zatrzymana lub usunięta z pierwszego planu.

Aby odpowiedzieć na to pytanie, tak, uruchomiona oddzielna Thread off o Activity będzie miał niższy priorytet niż Service uruchomiony w pierwszym planie, jeśli Activity który uruchomił Thread został zatrzymany/wstrzymane.

Osobiście polecam zrobić to w Service, ponieważ jest to dokładnie to, na co stworzono klasę Service.

Edit:

Ciekawe, co wydaje się sugerować, w przeciwieństwie do tego co czytałem (wszystko reaguje, gdy nie jest używany gwint w Service). Bez względu na to, prawdopodobnie powinien on zostać uruchomiony w wątku tła.

Wątek (wątek utworzony przez użytkownika) nie zostanie przerwany, chyba że proces się zakończy, a stanie się tak, gdy środowisko wykonawcze zdecyduje, że potrzebne są zasoby. Activity mogą zostać zabite, gdy nie są na pierwszym planie, więc ich Thread mogą zostać zniszczone. Jeśli masz oznaczony jako pierwszy plan, jest on mniej prawdopodobny, dlatego nie powinieneś mieć tego samego problemu.

+0

Dzięki! Czy możesz skierować moją edycję? – LuxuryMode

+1

Umieściłem moją mediaplayer zarówno w usłudze, jak i poza nią, w jej własnym wątku. Android zabije mediaplayer niezależnie od tego, gdzie się znajduje, jeśli potrzebuje więcej zasobów. I nie jest nawet mniej prawdopodobne, że zostanie zabity w ramach usługi, która ma priorytet na pierwszym planie niż w osobnym wątku. Jedynym miejscem, w którym wydaje się, że nigdy nie zostanie zabity, jest działanie, które jest obecnie na pierwszym planie. – AndroidDev

-1

Nie trzeba uruchamiać MediaPlayer z wątku. Dopóki używasz MediaPlayer.prepareAsync, zamiast MediaPlayer.prepare, w MediaPlayer nie ma żadnych metod, które blokują się na tyle długo, aby powodować problemy. Uruchom go na pierwszym planie w swojej usłudze.

Jeśli twój proces zostanie zabity, wątki idą z nim. Procesy obsługujące Usługi mają dłuższy czas życia niż Działania, pod warunkiem, że użytkownik wywołuje metodę Service.startForeground (i wyświetla obowiązkowe powiadomienie wymagane przez startForeground na pasku stanu). Gdy tylko działanie zostanie przerwane, cały proces staje się głównym kandydatem do recyklingu (zakładając, że w procesie tym nie ma również usługi pierwszoplanowej).

+4

Niestety, mimo że dokumentacja wskazuje, że readyAsync() jest wystarczająco dobry, to nie wystarczy. Inne wywołania inne niż prepare() mogą zawiesić aplikację, więc lepiej, aby instancja MediaPlayer była w swoim wątku. – ajacian81

7

Właśnie umieściłem część tej odpowiedzi w innym miejscu, ale nadal jest istotne.

Niestety, wywołanie metody prepareAsync() jest po prostu niewystarczające, aby uniknąć monitów ANR i zawieszenia aplikacji przez kilka sekund, szczególnie jeśli odtwarzasz plik z sieci. Najlepiej jest umieścić swoją instancję MediaPlayer we własnym wątku lub przynajmniej wykonać intensywne wywołania w Handler (jak mediaplayer.start()). Używam MediaPlayer od ponad roku i mogę powiedzieć, że na pewno zawiesza się po różnych połączeniach, w zależności od okoliczności.

Idealnie powinieneś utworzyć wątek, który kontroluje twój MediaPlayer z poziomu Usługi. W ten sposób upewnisz się, że Twoje multimedia są nadal odtwarzane, gdy aplikacja działa w tle, a wszelkie połączenia blokujące (oprócz funkcji prepare()/prepareAsync()) nie zawieszają aplikacji.

+1

Zgadzam się. Jednak muszę dodać, że widziałem, jak mediaplayer został zakończony, nawet w wątku zrodzonym z usługi. Wygląda na to, że mediaplayer ma własny wątek wewnętrzny, który ma jeszcze niższy priorytet niż usługa pierwszego planu i że Android chętniej zabija zarodek, zanim zakończy usługę. – AndroidDev

+0

Uważam, że to rozwiązuje problem lepiej niż zaakceptowane. W każdym razie, co chcę wiedzieć, czy muszę uruchomić osobny wątek nawet w usłudze? Obecnie używam zupełnie innego procesu, ale chcę przenieść go do głównego procesu. – frostymarvelous

+0

Usługa domyślnie działa w głównym wątku UI. Możemy utworzyć wątek/AsyncTask w usłudze. W zasadzie to zrobię. – ajacian81