Service
Transkrypt
Service
Programowanie usług działających w tle Android Paweł Szafer Po co programować usługi działające w tle? Plan prezentacji ● O aplikacjach w Androidzie, ● Sposób podejmowania decyzji o zabiciu procesu, ● Rodzaje procesów, ● Wątki, ● AsyncTask, ● Services, ○ Service, ■ unbound, ■ bound, ○ IntentService, ● Współdzielenie danych - ContentProvider, ● Komunikacja między procesami - BroadcastReceiver. Aplikacje ● Domyślnie wszystkie aplikacje działają w obrębie tego samego procesu, ● Android może zdecydować o zabiciu aplikacji, gdy nie ma wystarczającej ilości pamięci dla aplikacji ważniejszej i/lub obsługującej użytkownika, ● Wszystkie komponenty aplikacji są niszczone (wywoływana metoda onDestroy() ). Podejmowanie decyzji o zabiciu aplikacji W przypadku konieczności zabicia aplikacji tworzony jest ranking znaczenia aplikacji, tworzony w oparciu o: ● rodzaj komponentów działających w obrębie aplikacji, ● stan komponentów działających w obrębie aplikacji, Na podstawie powyższych danych tworzony jest ranking procesu. Im wyższy wynik tym mniej prawdopodobne zabicie aplikacji. Rodzaje procesów 1. Foreground process, ○ Activity, ○ Service odwołujący się do Activity, które użytkownik aktualnie używa, ○ Service, który został uruchomiony poprzez wywołanie metody startForeground(), ○ Service, który jest w jednej z następujących metod: ■ onCreate(), ■ onStart(), ■ onDestroy(). Ta kategoria prawie nigdy nie jest skierowana do zabicia. Rodzaje procesów 2. Visible process - proces, który nie posiada żadnych elementów pierwszego planu (widocznych na ekranie), ale może wpływać na zawartość ekranu użytkownika np. ● Activity, które jest w metodzie onPause() (w tle), ● Service, który współpracuje z Acitivty (będące procesem pierwszoplanowym lub widocznym). Procesy w tej kategorii są ekstremalnie ważne, a task killer w przypadku, gdy musi któryś z nich zabić, stara się zawsze poczekać aż zakończą one swoje działania. Rodzaje procesów 3. Service ● proces, który implementuje klasę Service, ● rozpoczęty poprzez wywołanie metody startService(), ● nie może zostać zakwalifikowany do żadnej z wcześniejszych kategorii, ● użytkownik nie może widzieć jego działania, ● Przykład: odtwarzanie muzyki, pobieranie danych z sieci. Rodzaje procesów 4. Background process: ● Activity, które nie jest aktualnie widoczne na ekranie (zatrzymane poprzez wywołanie onStop()), ● mogą zostać zatrzymane w każdym momencie działania, jeżeli system widzi taką potrzebę (np. zajmowanie pamięci dla procesów pierwszoplanowych, zbyt duże obciążenie procesora). Rodzaje procesów 5. Empty process ● aplikacja, która nie posiada żadnych aktywnych komponentów, ● jedyny powód dla systemu, aby działała: w celu cache'owania, aby przy kolejnym uruchomieniu aplikacja mogła szybciej zostać uruchomiona. Rodzaje procesów - podsumowanie 2 sytuacje: ● Wątek wywołany z Activity jest traktowany jako proces tła (4), ● Service wywołany z Activity ma ranking 3. Oznacza to, że lepiej uruchomić service, niż wątek (Activity, może oczekiwać w tle na zakończenie operacji wątku, który został zabity). Worker threads Zasady: ● nigdy nie blokuj wątku interfejsu użytkownika, ● nie próbuj dostać się do komponentów wątku interfejsu użytkownika spoza niego. Po około 5 sekundach braku odpowiedzi z Activity pojawia się komunikat o braku odpowiedzi aplikacji. W związku z tym nie można (z kilkoma wyjątkami) wywoływać blokujących operacji wewnątrz interfejsu użytkownika Worker threads Źle Zasada: nie próbuj dostać się do komponentów wątku interfejsu użytkownika spoza niego. Worker threads Aby umożliwić modyfikowanie elementów interfejsu użytkownika wykorzystuje się metody: ● Activity.runOnUiThread(Runnable), ● View.post(Runnable), ● View.postDelayed(Runnable, long). AsyncTask<Void, Void, Void> ● Przeznaczone do wywołania operacji asynchronicznych z poziomu interfejsu użytkownika, ● zadanie może być wywołane tylko jeden raz, ● posiada metody do interakcji z UI (onProgressUpdate()), ● gdy Activity przechodzi do działania w tle, w AsyncTask wywoływana jest metoda doInBackground(), wówczas AsyncTask ma ranking 4 (background process). Services ● klasa bazowa dla wszystkich Service, ● komponent aplikacji wykonujący długotrwałe operacje w tle, nie posiadający interfejsu użytkownika. ● aplikacja główna może zostać zamknięta, a service może nadal działać, ● inne aplikację mogą zarządzać usługą (np. w celu wyłączenia odtwarzania muzyki). Podział service's Started (unbound) - usługa uruchomiona poprzez wywołanie metody startService(). ● usługa może działać w tle dowolną ilość czasu, nawet gdy komponent ją uruchamiający został zabity, ● Service nie powinien zwracać wyników operacji do wywołującego ją komponentu, ● powinien sam się zatrzymać po wykonaniu operacji, ● dla każdej większej operacji powinien być zaprojektowany oddzielny Service (wiele czynności wykonywanych wewnątrz jednej usługi może zabierać za dużo pamięci i być w gorszej sytuacji w przypadku szukania procesu do zabicia przez system). Podział service's Bound - service jest powiązany, gdy jest wywołana poprzez metodę bindService(). Bound Service oferuje interfejs typu klient - serwer, dzięki któremu wiele komponentów może się z nią komunikować. Pozwala na: ● wysyłanie żądań, ● pobieranie wyników, ● umożliwia komunikację między kilkoma procesami. Ten rodzaj usługi działa tak długo, aż jakikolwiek proces jest do niej podłączony. Naraz, standardowo może być podłączona dowolna ilość procesów. Podział service's Oba rodzaje tj. Started i Bound mogą być zaimplementowane w jednej usłudze. Service również podlega pod systemowe sprawdzanie czy aplikacja nie została zawieszona (Application Not Responding error), co oznacza, że w przypadku operacji blokujących lub mających duże zapotrzebowanie na czas procesora wewnątrz usługi powinien być zaimplementowany oddzielny wątek na ich wykonanie. Service - implementacja IntentService ● klasa wywodząca się z Service, ● sama uruchamia wątek wywołujący żądanie, ● IntentService nie obsługuję wielokrotnego, współbieżnego wywołania (tylko jeden wątek w tym samym czasie), ● główna zaleta - konieczność zaimplementowania jednej metody onHandleIntent(). IntentService - implementacja Zarządzanie współdzielonymi danymi ● ContentProvider - zarządza współdzielonymi danymi. Dane mogą być przechowywane w sieci, w bazie danych SQLite. Implementuje metody do zarządzania współdzielonymi danymi (np. insert, query, delete, update), ● ContentResolver - zapewnia komunikację aplikacji z ContentProvider'em. Zazwyczaj nie jest konieczny do samodzielnej implementacji Żadna z powyższych klas nie implementuje interfejsu użytkownika. Zarządzanie współdzielonymi danymi ● ContentObserver - informuje zarejestrowane aplikację o zmianie danych przez ContentProvider'a, ● DataSetObserver - informuję o wywołaniu metody w ContentResolver, czyli również o odczycie danych i próbie dostępu (nawet jeżeli jest nieudana). Żadna z powyższych klas nie implementuje interfejsu użytkownika. Komunikacja między procesami/aplikacjami BroadcastReceiver: ● służy do rozgłaszania informacji np. Service może poinformować aplikację o zakończeniu pobierania, ● nie implementuje interfejsu użytkownika, ● może stworzyć powiadomienie na pasku powiadomień, ● zazwyczaj służy jedynie jako brama do komunikacji między komponentami np. w przypadku wystąpienia określonego wydarzenia może uruchomić zdefiniowany Service. KONIEC Materiały: ● http://developer.android.com