Piszę swoją pierwszą aplikację na Androida i staram się skupić na komunikacji między usługami i działaniami. Mam usługę, która będzie działać w tle i rejestrować dane GPS i czasowe. Będę miał działanie, które zostanie wykorzystane do uruchomienia i zatrzymania usługi.
Więc najpierw muszę być w stanie dowiedzieć się, czy usługa jest uruchomiona w momencie uruchomienia działania. Są tutaj inne pytania, więc myślę, że mogę to rozgryźć (ale nie krępuj się udzielić porady).
Mój prawdziwy problem: jeśli działanie jest uruchomione, a usługa jest uruchomiona, potrzebuję sposobu na wysłanie wiadomości do działania. Proste ciągi i liczby całkowite w tym momencie - głównie komunikaty o stanie. Wiadomości nie będą się pojawiać regularnie, więc nie sądzę, aby odpytywanie usługi było dobrym rozwiązaniem, jeśli istnieje inny sposób. Chcę tej komunikacji tylko wtedy, gdy użytkownik uruchomił działanie - nie chcę uruchamiać działania z usługi. Innymi słowy, jeśli uruchomisz działanie i usługa jest uruchomiona, zobaczysz komunikaty o stanie w interfejsie działania, gdy wydarzy się coś interesującego. Jeśli nie rozpoczniesz działania, nie zobaczysz tych wiadomości (nie są one tak interesujące).
Wygląda na to, że powinienem być w stanie ustalić, czy usługa jest uruchomiona, a jeśli tak, dodaj działanie jako detektora. Następnie usuń działanie jako detektora, gdy działanie zostanie wstrzymane lub zatrzymane. Czy to rzeczywiście możliwe? Jedyny sposób, w jaki mogę to zrobić, to mieć implementację działania Parcelable i zbudować plik AIDL, aby móc go przekazać przez zdalny interfejs Usługi. Wydaje się to jednak przesadą i nie mam pojęcia, w jaki sposób działanie powinno implementować writeToParcel () / readFromParcel ().
Czy istnieje łatwiejszy lub lepszy sposób? Dziękuję za wszelką pomoc.
EDYTOWAĆ:
Dla każdego, kto jest zainteresowany tym później, w katalogu przykładów znajduje się przykładowy kod od Google do obsługi tego za pośrednictwem AIDL: /apis/app/RemoteService.java
źródło
busy-wait
działanie? Czy możesz to wyjaśnić?Activity.onCreate()
?Intents
, wysyłając daneParcellable
między wiadomościami?Pytający zapewne już dawno temu przeszedł, ale na wypadek, gdyby ktoś szukał tego ...
Jest inny sposób na poradzenie sobie z tym, który moim zdaniem może być najprostszy.
Dodaj a
BroadcastReceiver
do swojej aktywności. Zarejestruj go, aby otrzymać niestandardowe zamiaryonResume
i wyrejestruj goonPause
. Następnie wyślij ten zamiar ze swojej usługi, jeśli chcesz wysłać aktualizacje statusu lub co masz.Upewnij się, że nie będziesz nieszczęśliwy, jeśli jakaś inna aplikacja wysłucha Twojej
Intent
(czy ktoś może zrobić coś złośliwego?), Ale poza tym powinieneś być w porządku.Zażądano próbki kodu:
W mojej służbie mam to:
(
RefreshTask.REFRESH_DATA_INTENT
jest tylko ciągiem ciągłym).W mojej działalności związanej ze słuchaniem definiuję swoje
BroadcastReceiver
:Deklaruję mój odbiornik na szczycie klasy:
Zastępuję,
onResume
aby dodać to:I zastępuję,
onPause
aby dodać:Teraz moja aktywność oczekuje, że moja usługa powie „Hej, idź się zaktualizuj”. Mogę przekazywać dane
Intent
zamiast aktualizować tabele bazy danych, a następnie wracać, aby znaleźć zmiany w ramach mojej działalności, ale ponieważ chcę, aby zmiany nadal się utrzymywały, sensowne jest przekazywanie danych przez DB.źródło
Broadcasts
są fantastyczne, a ponadto, jeśli nie chcesz, aby transmisja wykraczała poza własny proces, rozważ użycieLocalBroadcast
: developer.android.com/reference/android/support/v4/content/…Służy
LocalBroadcastManager
do rejestrowania odbiornika w celu nasłuchiwania transmisji wysyłanej z lokalnego serwisu w Twojej aplikacji, odnośnik znajduje się tutaj:http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
źródło
LocalBroadcastManager
jest teraz przestarzałe na rzeczLiveData
lub innych narzędzi wzorców obserwatora: developer.android.com/reference/androidx/localbroadcastmanager/…Dziwi mnie, że nikt nie wspomniał o bibliotece Bus wydarzenie Otto
http://square.github.io/otto/
Używam tego w moich aplikacjach na Androida i działa bezproblemowo.
źródło
android:process=":my_service"
, nie mogą się komunikować.Korzystanie z komunikatora to kolejny prosty sposób komunikowania się między usługą a działaniem.
W działaniu utwórz moduł obsługi z odpowiednim komunikatorem. Będzie to obsługiwać wiadomości z Twojej Usługi.
Komunikator można przekazać do usługi, dołączając go do wiadomości:
Pełny przykład można znaleźć w prezentacjach API: MessengerService i MessengerServiceActivity . Zapoznaj się z pełnym przykładem działania MyService.
źródło
myService.send(message);
powinien byćmessenger.send(message);
zamiast.Inną metodą, która nie została wymieniona w innych komentarzach, jest powiązanie usługi z działaniem za pomocą bindService () i uzyskanie wystąpienia usługi w wywołaniu zwrotnym ServiceConnection. Jak opisano tutaj http://developer.android.com/guide/components/bound-services.html
źródło
Możesz także użyć,
LiveData
który działa jakEventBus
.Następnie dodaj obserwatora z twojego
Activity
.Możesz przeczytać więcej z tego bloga.
źródło
Innym sposobem może być użycie obserwatorów z fałszywą klasą modelu poprzez działanie i samą usługę, implementując odmianę wzoru MVC. Nie wiem, czy to najlepszy sposób, aby to osiągnąć, ale tak mi się to udało. Jeśli potrzebujesz jakiegoś przykładu, poproś o to, a ja coś opublikuję.
źródło
Moja metoda:
Klasa zarządzająca wysyłaniem i odbieraniem wiadomości od / do usługi / działalności:
W przykładzie działania:
W przykładzie serwisowym:
Wyślij wiadomość z działania / usługi:
Jak to działa:
na działalność, którą uruchamiasz lub wiążesz z usługą. Metody usługi „OnBind” zwracają Binder do jego menedżera komunikatów MessageManager, aw działaniu poprzez implementację metod interfejsu „Połączenie usługi” „OnServiceConnected” dostajesz tego IBindera i inicjujesz korzystanie z niego przy pomocy menedżera komunikatów. Po zainicjowaniu działania MessageManager przez MessageHandler, usługa MessageHandler wysyła i uzgadnia z serwisem, aby mógł ustawić swojego nadawcę „MessageHandler” („private Messenger mMsgSender;” w MessageManager). W ten sposób usługa wie, kto wysyła jego wiadomości.
Można to również zaimplementować za pomocą „nadawcy” listy / kolejki komunikatora w menedżerze wiadomości, aby można było wysyłać wiele wiadomości do różnych działań / usług lub można użyć „odbiornika” listy / kolejki komunikatora w menedżerze wiadomości, aby otrzymywać wiele wiadomość z różnych działań / usług.
W instancji „MessageManager” masz listę wszystkich otrzymanych wiadomości.
Jak widać połączenie między „Activity's Messenger” a „Service Messenger” za pomocą tego wystąpienia „MessageManager” odbywa się automatycznie, odbywa się to za pomocą metody „OnServiceConnected” i za pomocą „Handshake”.
Mam nadzieję, że jest to dla ciebie pomocne :) Dziękuję bardzo! Pa: D
źródło
Aby śledzić odpowiedź @MrSnowflake na przykładzie kodu. To jest teraz
Application
klasa open source XABBER .Application
Klasa centralizację i koordynowanieListeners
i ManagerInterfaces i więcej. Menedżerowie wszelkiego rodzaju są ładowani dynamicznie.Activity´s
rozpoczęty w Xabber zgłosi, jakiego rodzajuListener
są. A kiedyService
zaczyna, raportuje doApplication
klasy, jak zaczął. Teraz, aby wysłać wiadomość naActivity
wszystko, co musisz zrobić, to twójActivity
stały sięlistener
od tego, co trzeba wpisać. WOnStart()
OnPause()
rejestrze / unreg.Service
Może zwrócić się doApplication
klasy dla tylko, żelistener
to trzeba mówić do i jeśli jest tam wtedy aktywny jest gotowy do odbioru.Przechodząc przez
Application
klasę zobaczysz, że dzieje się coś więcej niż to.źródło
Wiązanie to kolejny sposób komunikacji
Zaimplementuj interfejs w działaniu
Podaj implementację metody
Powiąż działanie z usługą
Zarejestruj się i wyrejestruj oddzwonienie, gdy usługa zostanie powiązana i niezwiązana z Działaniem.
Zainicjuj oddzwonienie
W razie potrzeby wywołuj metodę wywołania zwrotnego
źródło
serviceConnection
jest zonCreate
. Edytuj to.Jak wspomniał Madhur, do komunikacji można użyć autobusu.
W przypadku korzystania z magistrali masz kilka opcji:
Biblioteka magistrali zdarzeń Otto (przestarzała na rzecz RxJava)
http://square.github.io/otto/
EventBus Green Robot
http://greenrobot.org/eventbus/
NYBus (RxBus, zaimplementowany przy użyciu RxJava. Bardzo podobny do EventBus)
https://github.com/MindorksOpenSource/NYBus
źródło
Oprócz LocalBroadcastManager, Event Bus i Messenger już odpowiedział na to pytanie, możemy użyć Pending Intent do komunikacji z serwisu.
Jak wspomniano tutaj w moim blogu
źródło