Czy odrzucenie aplikacji jest niezadowolone?


1151

Kontynuując próbę nauki Androida, po prostu przeczytałem :

Pytanie: Czy użytkownik ma możliwość zabicia aplikacji, chyba że wprowadzimy opcję menu, aby ją zabić? Jeśli taka opcja nie istnieje, w jaki sposób użytkownik kończy aplikację?

Odpowiedź: (Romain Guy): Użytkownik nie, system obsługuje to automatycznie. Do tego właśnie służy cykl życia aktywności (szczególnie onPause / onStop / onDestroy). Bez względu na to, co robisz, nie umieszczaj przycisku aplikacji „wyjdź” lub „wyjdź”. Jest to bezużyteczne w przypadku modelu aplikacji Androida. Jest to również sprzeczne z działaniem podstawowych aplikacji.

Hehe, na każdym kroku w świecie Androida napotykam jakiś problem = (

Najwyraźniej nie można zamknąć aplikacji w systemie Android (ale system Android może bardzo dobrze całkowicie zniszczyć aplikację, gdy tylko ma na to ochotę). O co chodzi? Zaczynam myśleć, że nie można napisać aplikacji, która działa jak „normalna aplikacja” - że użytkownik może zamknąć aplikację, gdy zdecyduje się to zrobić. To nie jest coś, na co powinien polegać system operacyjny.

Aplikacja, którą próbuję utworzyć, nie jest aplikacją dla Android Market. To nie jest aplikacja do „szerokiego zastosowania” przez ogół społeczeństwa, to aplikacja biznesowa, która będzie używana w bardzo wąskiej branży.

Naprawdę nie mogłem się doczekać rozwoju platformy Android, ponieważ rozwiązuje ona wiele problemów występujących w systemach Windows Mobile i .NET. Jednak ostatni tydzień był dla mnie trochę kłopotliwy ... Mam nadzieję, że nie muszę rezygnować z Androida, ale teraz nie wygląda to zbyt dobrze = (

Czy istnieje sposób, aby naprawdę zamknąć aplikację?

Odpowiedzi:


1285

W końcu przejdzie to do twojego pytania, ale najpierw chcę rozwiązać kilka kwestii poruszonych w różnych komentarzach do różnych odpowiedzi udzielonych już w momencie pisania tego tekstu. Nie mam zamiaru zmieniać zdania - są one raczej przeznaczone dla innych osób, które będą czytać ten post w przyszłości.

Chodzi o to, że nie mogę pozwolić, aby Android określił, kiedy moja aplikacja ma zostać zakończona. taki musi być wybór użytkownika.

Miliony ludzi są całkowicie zadowolone z modelu, w którym środowisko zamyka aplikację w razie potrzeby. Ci użytkownicy po prostu nie myślą o „zakończeniu” aplikacji na Androida, podobnie jak o „zakończeniu” strony internetowej lub „zakończeniu” termostatu.

Użytkownicy iPhone'a są w podobny sposób, ponieważ naciśnięcie przycisku iPhone'a niekoniecznie „czuje”, że aplikacja została zakończona, ponieważ wiele aplikacji iPhone'a odbiera miejsce, w którym użytkownik przerwał, nawet jeśli aplikacja naprawdę została zamknięta (ponieważ tylko iPhone obecnie umożliwia korzystanie z jednej aplikacji innej firmy).

Jak powiedziałem powyżej, w mojej aplikacji dzieje się wiele rzeczy (dane są PUSHed do urządzenia, listy z zadaniami, które zawsze powinny tam być, itp.).

Nie wiem, co oznaczają „listy z zadaniami, które zawsze powinny tam być”, ale „dane przekazywane do urządzenia” to przyjemna fikcja i w żadnym wypadku nie powinny być wykonywane przez działanie. Użyj zaplanowanego zadania (via AlarmManager), aby zaktualizować dane w celu uzyskania maksymalnej niezawodności.

Nasi użytkownicy logują się i nie mogą robić tego za każdym razem, gdy otrzymają telefon, a Android zdecyduje się zabić aplikację.

Jest wiele aplikacji na iPhone'a i Androida. Zwykle dzieje się tak, ponieważ utrzymują oni poświadczenia logowania, a nie zmuszają użytkowników do logowania za każdym razem ręcznie.

Na przykład chcemy sprawdzić aktualizacje przy wychodzeniu z aplikacji

To błąd w każdym systemie operacyjnym. Z tego, co wiesz, przyczyną „zamknięcia” aplikacji jest zamknięcie systemu operacyjnego, a następnie proces aktualizacji zakończy się niepowodzeniem w połowie strumienia. Ogólnie rzecz biorąc, to nie jest dobra rzecz. Sprawdź aktualizacje przy starcie lub sprawdź aktualizacje całkowicie asynchronicznie (np. Poprzez zaplanowane zadanie), nigdy przy wyjściu.

Niektóre komentarze sugerują, że naciśnięcie przycisku Wstecz wcale nie zabija aplikacji (patrz link w moim pytaniu powyżej).

Naciśnięcie przycisku WSTECZ nie powoduje „zabicia aplikacji”. Kończy działanie, które było na ekranie, gdy użytkownik nacisnął przycisk WSTECZ.

Powinien on zostać zakończony tylko wtedy, gdy użytkownicy chcą go rozwiązać - nigdy w żaden inny sposób. Jeśli nie możesz pisać takich aplikacji w Androidzie, myślę, że Androida nie można używać do pisania prawdziwych aplikacji = (

Zatem aplikacje sieciowe również nie mogą. Lub WebOS , jeśli dobrze rozumiem ich model (jeszcze nie miałem okazji z nim grać). We wszystkich z nich użytkownicy niczego nie „kończą” - po prostu wychodzą. iPhone jest nieco inny, ponieważ obecnie pozwala tylko na uruchamianie jednej rzeczy naraz (z kilkoma wyjątkami), a zatem opuszczenie aplikacji oznacza dość natychmiastowe zakończenie aplikacji.

Czy istnieje sposób, aby naprawdę zamknąć aplikację?

Jak wszyscy ci mówili, użytkownicy (przez POWRÓT) lub kod (przez finish()) mogą zamknąć bieżącą aktywność. Użytkownicy zwykle nie potrzebują niczego więcej, do poprawnie napisanych aplikacji, bardziej niż potrzebują opcji „wyjdź” do korzystania z aplikacji internetowych.


Z definicji nie ma dwóch takich samych środowisk aplikacji. Oznacza to, że możesz obserwować trendy w środowiskach, gdy pojawiają się nowe, a inne zostają pochowane.

Na przykład rośnie ruch próbujący wyeliminować pojęcie „pliku”. Większość aplikacji internetowych nie zmusza użytkowników do myślenia o plikach. Aplikacje iPhone zazwyczaj nie zmuszają użytkowników do myślenia o plikach. Aplikacje na Androida zazwyczaj nie zmuszają użytkowników do myślenia o plikach. I tak dalej.

Podobnie rośnie ruch próbujący wyeliminować pojęcie „zakończenia” aplikacji. Większość aplikacji sieci Web nie wymusza wylogowania użytkownika, ale domyślnie wylogowuje użytkownika po okresie bezczynności. To samo dotyczy Androida i, w mniejszym stopniu, iPhone'a (i ewentualnie WebOS).

Wymaga to większego nacisku na projektowanie aplikacji, koncentrowanie się na celach biznesowych i nieprzestrzeganie modelu implementacji powiązanego z poprzednim środowiskiem aplikacji. Programiści, którym brakuje czasu lub ochoty na zrobienie tego, będą sfrustrowani nowszymi środowiskami, które łamią istniejący model mentalny. Nie jest to wina żadnego środowiska, podobnie jak wina góry, a nie burz, które przepływają wokół niej.

Na przykład w niektórych środowiskach programistycznych, takich jak Hypercard i Smalltalk, aplikacja i narzędzia programistyczne były połączone w jednym zestawie. Ta koncepcja nie przyciągnęła zbyt wiele, poza rozszerzeniami językowymi aplikacji (np. VBA w Excelu , Lisp w AutoCAD ). Programiści, którzy wymyślili modele mentalne, które zakładały istnienie narzędzi programistycznych w samej aplikacji, musieli zatem zmienić swój model lub ograniczyć się do środowisk, w których ich model byłby prawdziwy.

Kiedy piszesz:

Wraz z innymi bałaganami, które odkryłem, myślę, że opracowanie naszej aplikacji na Androida nie nastąpi.

To wydaje się być najlepsze dla ciebie, na teraz. Podobnie odradzałbym ci próbę przeniesienia aplikacji do sieci, ponieważ niektóre z tych samych problemów, które zgłosiłeś z Androidem, znajdziesz również w aplikacjach internetowych (np. Brak „zakończenia”). Albo odwrotnie, jeśli kiedyś zrobić portu aplikacji do sieci, może się okazać, że przepływ aplikacji sieci Web mogą być lepiej dopasowane do Androida i można ponownie port Androida w tym czasie.


21
Jedna myśl przyszła mi do głowy: jeśli po prostu przepiszę całą aplikację jako Usługę i potraktuję tę Usługę jako rzeczywistą aplikację - może to działałoby lepiej? Następnie mógłbym „stępić” Działania (tak jak chce tego Android), aby po prostu przedstawić dane zawarte w Serwisie. W takim przypadku mógłbym być może utrzymać stan logowania i inne dane. Za pomocą startForeground (int, Powiadomienie) mogę prawie powstrzymać Androida przed zabiciem Usługi ...?
Ted

66
„Pamiętaj, że moi użytkownicy to profesjonaliści, którzy używają urządzenia wyłącznie w celu korzystania z aplikacji, którą próbuję przenieść na system Android”. Właściwie wskazałeś inaczej („nie mogę tego robić za każdym razem, gdy otrzymają połączenie telefoniczne” - „połączenie telefoniczne” nie jest Twoją aplikacją). Ponadto, chyba że budujesz własne urządzenie, nie możesz uniemożliwić innym instalowania innych aplikacji, jeśli tak zdecydują.
CommonsWare

25
@SomeCallMeTim: Nie, to nie jest prawidłowy powód do użycia killProcess(). Jest to ważny powód, aby pisać lepszy kod iOS.
CommonsWare 30.10.10

24
@CommonsWare: Przepraszam, ale to banalna odpowiedź, która mi się nie przydaje. Przenoszę kod, za który płacę do portu. Czy powinienem spędzić dwa razy więcej czasu na portowaniu, przepisywaniu kodu, czy też robiąc to w sposób, który zmniejsza koszty dla mojego pracodawcy, pozwalając im na wcześniejsze zainstalowanie większej ilości gier na Androidzie? W każdym razie jest to całkowicie akademickie pytanie: nie chcą, żebym wprowadził tak poważne zmiany w silniku, ponieważ nie mogę przetestować tych zmian na iOS. I to po prostu źle: nie ma nic „złego” w stosowaniu wzorców Singleton dla odpowiednich obiektów. Android to po prostu zepsute aplikacje WRT NDK.
SomeCallMeTim

10
@Ted dla bardziej niezawodnej ponownej inicjalizacji, być może możesz zminimalizować ilość stanu przechowywanego w samym działaniu lub usłudze. Zamiast tego umieść większość stanu i kodu w osobnej klasie, którą odtwarzasz „od zera” przy każdym uruchomieniu działania lub usługi.
Qwertie

289

Chciałbym tylko dodać tutaj poprawkę dla przyszłych czytelników tego wątku. Ten szczególny niuans umknął mi przez długi czas, dlatego chcę się upewnić, że nikt z was nie popełni takich samych błędów:

System.exit()nie zabija Twojej aplikacji, jeśli masz więcej niż jedno działanie na stosie. W rzeczywistości proces jest zabijany i natychmiast uruchamiany ponownie z jedną mniejszą aktywnością na stosie. To samo dzieje się, gdy twoja aplikacja zostanie zabita przez okno Wymuś zamknięcie lub nawet gdy spróbujesz zabić proces z DDMS. Według mojej wiedzy jest to całkowicie nieudokumentowane.

Krótka odpowiedź brzmi: jeśli chcesz wyjść z aplikacji, musisz śledzić wszystkie działania na stosie i finish()WSZYSTKIE z nich, gdy użytkownik chce wyjść (i nie, nie ma sposobu na iterację przez stos działań , więc musisz sam sobie z tym wszystkim poradzić). Nawet to tak naprawdę nie zabija procesu ani żadnych wiszących referencji. Po prostu kończy działania. Nie jestem też pewien, czy Process.killProcess(Process.myPid())działa lepiej; Nie testowałem tego.

Jeśli z drugiej strony możesz pozostawać na stosie, możesz skorzystać z innej metody, która sprawia, że ​​wszystko jest dla ciebie bardzo łatwe: Activity.moveTaskToBack(true)po prostu opisze proces i wyświetli ekran główny.

Długa odpowiedź obejmuje wyjaśnienie filozofii tego zachowania. Filozofia zrodziła się z szeregu założeń:

  1. Po pierwsze dzieje się tak tylko wtedy, gdy aplikacja jest na pierwszym planie. Jeśli jest w tle, proces zakończy się dobrze. Jeśli jednak znajduje się na pierwszym planie, system operacyjny zakłada, że ​​użytkownik chce kontynuować to, co robił. (Jeśli próbujesz zabić proces z DDMS, powinieneś najpierw nacisnąć przycisk Home, a następnie go zabić)
  2. Zakłada również, że każde działanie jest niezależne od wszystkich innych działań. Jest to często prawdą, na przykład w przypadku, gdy aplikacja uruchamia działanie przeglądarki, które jest całkowicie odrębne i nie zostało napisane przez Ciebie. Działanie przeglądarki może, ale nie musi zostać utworzone dla tego samego zadania, w zależności od jego manifestów.
  3. Zakłada, że ​​każda z twoich czynności jest całkowicie samowystarczalna i może zostać zabita / przywrócona w mgnieniu oka. (Raczej nie podoba mi się to szczególne założenie, ponieważ moja aplikacja ma wiele działań, które opierają się na dużej ilości buforowanych danych, zbyt dużych, aby można je było skutecznie serializować podczasonSaveInstanceState , ale co zrobisz?) W przypadku większości dobrze napisanych aplikacji na Androida powinno to być prawdą, ponieważ nigdy nie wiadomo, kiedy aplikacja zostanie zabita w tle.
  4. Ostatnim czynnikiem jest nie tyle założenie, ale raczej ograniczenie systemu operacyjnego: jawne zabicie aplikacji jest tym samym, co awaria aplikacji, a także to samo, co Android zabicie aplikacji w celu odzyskania pamięci. Kulminuje to nasz zamach stanu: ponieważ Android nie może stwierdzić, czy aplikacja wyszła, uległa awarii, czy też została zabita w tle, zakłada, że ​​użytkownik chce wrócić tam, gdzie ją przerwał, a zatem ActivityManager ponownie uruchamia proces.

Kiedy myślisz o tym, jest to odpowiednie dla platformy. Po pierwsze, dokładnie tak się dzieje, gdy proces jest zabijany w tle, a użytkownik do niego wraca, więc należy go ponownie uruchomić w miejscu, w którym został przerwany. Po drugie, dzieje się tak, gdy aplikacja ulega awarii i wyświetla przerażające okno dialogowe Force Close.

Powiedz, że chcę, aby moi użytkownicy mogli zrobić zdjęcie i przesłać je. Z mojej aktywności uruchamiam Aktywność kamery i proszę o zwrócenie obrazu. Kamera jest umieszczana na górze mojego bieżącego zadania (zamiast być tworzona we własnym zadaniu). Jeśli w aparacie wystąpił błąd i ulega awarii, czy powinno to spowodować awarię całej aplikacji? Z punktu widzenia użytkownika tylko kamera uległa awarii i należy ją przywrócić do poprzedniej aktywności. Więc po prostu restartuje proces z tymi samymi Aktywnościami na stosie, minus Kamera. Ponieważ Twoje działania powinny być zaprojektowane tak, aby można je było zabijać i przywracać za jednym razem, nie powinno to stanowić problemu. Niestety nie wszystkie aplikacje można tak zaprojektować, więc tak jest stanowić problem dla wielu z nas, bez względu na to, co powie Ci Romain Guy lub ktokolwiek inny. Musimy więc zastosować obejścia.

Tak więc moja rada na zakończenie:

  • Nie próbuj zabijać procesu. Zadzwoń finish()do wszystkich czynności lub zadzwoń moveTaskToBack(true).
  • Jeśli Twój proces ulegnie awarii lub zostanie zabity i jeśli, podobnie jak ja, potrzebujesz danych, które zostały utracone w pamięci, musisz wrócić do działania root. Aby to zrobić, powinieneś zadzwonić startActivity()z intencją, która zawiera Intent.FLAG_ACTIVITY_CLEAR_TOPflagę.
  • Jeśli chcesz zabić swoją aplikację z perspektywy Eclipse DDMS, lepiej, żeby nie była na pierwszym planie, albo uruchomi się ponownie. Najpierw naciśnij przycisk Początek, a następnie zakończ proces.

8
Właściwie, odkąd zacząłem ponownie od Androida, kończę wszystkie działania (tylko jedna aktywność jest aktywna w dowolnym momencie), a następnie wywołuję System.exit (0); w mojej usłudze - i to działa tak, jak ja tego chcę. Wiem, że większość osób mówi „nie rób tego”, ale dzięki temu ruchowi
Ted

13
Zabicie tego procesu jest czasami bardzo przydatne - na przykład podczas pisania gier, które używają natywnego kodu. Zabicie procesu oznacza natychmiastowe zwolnienie całej przydzielonej pamięci z powrotem do systemu.
Sulthan,

10
Dla każdego, kogo to obchodzi, Process.killProcess wykazuje dokładnie takie samo zachowanie jak System.exit ()
PacificSky

6
Wszystkie działania pochodzą ze wspólnej bazy AtivityBase. Następnie przytrzymaj flagę, aby wymusić zamknięcie aplikacji, w opcji OnResume sprawdź, czy ustawiona jest flaga wymuszenia zamknięcia. Jeśli tak, wywołaj System.exit (0); Spowoduje to kaskadowe przechodzenie przez cały stos aktywności i wreszcie całkowicie zamknie aplikację.
Nar Gar

12
Dzięki za udzielenie rzeczywistych odpowiedzi ( moveTaskToBack()tego szukałem). Tak wiele osób mówi tylko: „Nie, jesteś idiotą, który chce wyjść z aplikacji”. nawet nie biorąc pod uwagę, że mogą istnieć przypadki, w których chcesz (np. nieudane logowanie).
Timmmm,

179

Wszystkie moje aplikacje mają przyciski zamykania ... i dość często otrzymuję pozytywne komentarze od użytkowników z tego powodu. Nie obchodzi mnie, czy platforma została zaprojektowana w taki sposób, że aplikacje nie powinny ich potrzebować. Mówienie „nie umieszczaj ich tam” jest trochę śmieszne. Jeśli użytkownik chce odejść ... Zapewniam mu dostęp do robienia dokładnie tego. Nie sądzę, żeby to w ogóle zmniejszyło działanie Androida i wydaje się dobrą praktyką. Rozumiem cykl życia ... i spostrzegłem, że Android nie radzi sobie z nim dobrze ... i to jest podstawowy fakt.


15
+1, ponieważ niestety nie robi tak dobrze w tym momencie (ale nadal chcę próbować robić rzeczy zgodnie z planem, więc stawia mnie to w niepewności)
Richard Le Mesurier

25
Jakiego mechanizmu używasz do wyjścia?
Gary Rudolph

4
@Igor finish () - działanie nie powoduje śmierci aplikacji (rozszerza aplikację). Więc nawet jeśli żadne z działań nie było aktywne, ustawienia są nadal aktywne i aktualne, tak że gdy działania będą próbowały uzyskać do nich dostęp, będą to te, które były używane wcześniej. System.exit (0); z drugiej strony zabija aplikację, tak że po ponownym uruchomieniu aplikacja będzie musiała zainicjować ustawienia od nowa. Tego potrzebuję przy ręcznej aktualizacji aplikacji, ponieważ często zmieniam format danych i potrzebuję ich natychmiastowej ponownej inicjacji.
Nar Gar

1
Cóż, w tej chwili jest to jedyny sposób na osiągnięcie tego, czego potrzebuję. Korzystam z system.exit, gdy aplikacja jest aktualizowana (w przeciwnym razie uzyskam wyjątki serializacji lub wyjątków rzutowania klas na podstawie moich zmian kodu). Powinienem jednak wspomnieć, że nie daję użytkownikowi uchwytu interfejsu użytkownika, aby zabić aplikację przez system.exit - to zarezerwowane dla mnie jako inżyniera aplikacji, z którego można korzystać tylko wtedy, gdy aplikacja absolutnie musi się całkowicie rozładować. Przez resztę czasu używane jest proste zakończenie () (lub domyślna operacja przycisku powrotu).
Nar Gar

13
Tak ... do diabła z „niestandardowym Androidem” .. Android jest potężny, ponieważ pozwala ludziom eksperymentować .. Jeśli zapewnia interfejsy API do zrobienia czegoś, jak można powiedzieć, że nie jest standardem Android? Nie potrafię przetrawić wszystkich tych „filozoficznych” odpowiedzi. Tworzysz aplikację z myślą o użytkownikach. jeśli są szczęśliwi lub chcą zobaczyć tę funkcję, to absolutnie dobrze jest ją wdrożyć, nawet jeśli tak zwani filozofowie są temu przeciwni.
Rahul

144

Przestań myśleć o swojej aplikacji jako aplikacji monolitycznej. Jest to zestaw ekranów interfejsu użytkownika, w których użytkownik może wchodzić w interakcje z „aplikacją” i „funkcjami” udostępnianymi za pośrednictwem usług Androida.

Nieznajomość tego, co „tajemnicza aplikacja” robi, nie jest tak naprawdę ważna. Załóżmy, że tuneluje się do super bezpiecznego korporacyjnego intranetu, wykonując pewne monitorowanie lub interakcję i pozostaje zalogowany, dopóki użytkownik „nie opuści aplikacji”. Ponieważ zarządza nim dział IT, użytkownicy muszą być bardzo świadomi tego, kiedy znajdują się w sieci intranet lub poza nią. Dlatego też sposób, w jaki użytkownicy powinni „rzucić”, jest ważny.

To jest proste. Wykonaj usługę, która umieszcza bieżące powiadomienie na pasku powiadomień z informacją: „Jestem w intranecie lub działam”. Niech ta usługa wykona wszystkie funkcje potrzebne do Twojej aplikacji. Wykonuj czynności powiązane z tą usługą, aby umożliwić użytkownikom dostęp do bitów interfejsu użytkownika, których potrzebują do interakcji z Twoją „aplikacją”. I mieć menu Android -> Wyjdź (lub wyloguj się, lub cokolwiek) przycisk, który każe usłudze zakończyć, a następnie zamyka samą aktywność.

To jest, dla wszystkich celów i celów dokładnie to, co chcesz powiedzieć. Wykonano na Androida. Spójrz na Google Talk lub Nawigację w Mapach Google, aby zobaczyć przykłady tego „wyjścia” to możliwa mentalność. Jedyna różnica polega na tym, że naciśnięcie przycisku Wstecz poza aktywność może pozostawić proces UNIX czekający na wypadek, gdyby użytkownik chciał ożywić aplikację. To tak naprawdę nie różni się od nowoczesnego systemu operacyjnego, który buforuje ostatnio używane pliki w pamięci. Po zamknięciu programu Windows najprawdopodobniej potrzebne zasoby są nadal w pamięci i czekają na zastąpienie innymi zasobami, ponieważ są ładowane teraz, gdy nie są już potrzebne. Android jest tym samym.

Naprawdę nie widzę twojego problemu.


3
@Eric, Nie widzisz problemu, ponieważ uciekasz przed nim. Po prostu użyłeś innego programu, który działa na starym „modelu programu”, aby zrobić to, czego nie da się zrobić za pomocą „modelu Androida”. Aby zobaczyć problem z „modelem systemu Android”, musisz sobie wyobrazić, że nie masz luksusu delegowania zadań na urządzenia z systemem Linux / Windows. Musisz sobie wyobrazić, że jesteś zmuszony do robienia wszystkiego, od frontendend do backendendu tylko przy użyciu urządzeń z „modelem Androida”. Następnie zobaczysz, że ograniczenia „modelu Androida” są tak jasne, jak niebo.
Pacerier

pomyśl o swojej aplikacji jako o monolitycznej aplikacji. Jest napisany w języku Java, który jest wykonywany przez pojedynczy proces JVM (Java Virtual Machine). System.exit () wychodzi z JVM i całkowicie i całkowicie kończy wszystkie ekrany interfejsu użytkownika i wszystko. Wyjątkiem jest JEŚLI programista ma problem z konfiguracją wielu wątków, które działają w wielu procesach - ale domyślnie tak NIE jest i według Google nie powinno się tego robić normalnie.
Jesse Gordon

@JesseGordon To po prostu nieprawda. System.exit()usuwa tylko aktywność ze stosu. JVM jest natychmiast ponownie inicjowany. Zobacz tę odpowiedź .
forresthopkinsa

1
@forresthopkinsa OK Testowałem to na Androidzie 7.0. Prosta aplikacja jednowątkowa nadal działa we własnej dedykowanej instancji JVM, działając jako identyfikator użytkownika unikalny dla tej aplikacji. Do tego testu nie próbowałem jeszcze aplikacji wielowątkowej. A System.exit () STILL zabija cały JVM dla tej aplikacji. Jeśli funkcja System.exit () jest wywoływana z działania podstawowego, po prostu kończy działanie. Jeśli funkcja System.exit () zostanie wywołana z podaktywności, maszyna JVM nadal jest zabijana, ale system Android uruchamia ją ponownie pod nowym identyfikatorem procesu z powrotem przy głównej / pierwszej aktywności. android.os.Process.killProcess (android.os.Process.myPid ()); i kill <pid> działają w ten sam sposób.
Jesse Gordon

1
Ciekawe .. Patrząc na odpowiedź, którą podłączyłeś, @forresthopkinsa, wygląda na to, że Android działa jak przeglądarki internetowe, przywracając działania po system.exit, aby użytkownik nie zauważył, że został zakończony, ale wykluczając działanie, które spowodowało wyjście. .? Dziwne. Ale tak czy inaczej, System.exit () robi blisko wszystkich działań i free () 's pamięć i kończy JVM dla tej aplikacji. Ale nie mam pojęcia, jakie wygłupy robi Android, aby go zrestartować / przywrócić. Czy to udaremnia aplikacje typu Killer? Sądzę więc, że jeśli ktoś chce przycisku wyjścia, powinien umieścić go w głównej aktywności.
Jesse Gordon

71

To interesująca i wnikliwa dyskusja z udziałem wielu ekspertów. Wydaje mi się, że ten post powinien być zapętlony z poziomu głównej strony internetowej poświęconej programowaniu systemu Android, ponieważ obraca się wokół jednego z podstawowych projektów systemu operacyjnego Android.

Chciałbym również dodać tutaj moje dwa centy.

Do tej pory byłem pod wrażeniem sposobu, w jaki Android obsługuje zdarzenia związane z cyklem życia, wprowadzając koncepcję podobną do sieci w natywnych aplikacjach.

Powiedziawszy, że nadal uważam, że powinien istnieć Quitprzycisk. Dlaczego? ... nie dla mnie, Teda ani żadnego z guru technologii tutaj, ale wyłącznie w celu zaspokojenia zapotrzebowania użytkownika końcowego.

Chociaż nie jestem wielkim fanem systemu Windows, ale dawno temu wprowadzili koncepcję, do której przyzwyczaja się większość użytkowników końcowych (przycisk X) ... „Chcę zrezygnować z uruchamiania widżetu, gdy„ chcę ”.

To nie znaczy, że ktoś (OS, programista?) Zajmie się tym według własnego uznania ... oznacza po prostu „gdzie jest mój czerwony przycisk X, do którego jestem przyzwyczajony”. Moje działanie powinno być analogiczne do „zakończenia połączenia po naciśnięciu przycisku”, „wyłączenia urządzenia poprzez naciśnięcie przycisku” itd. I tak dalej ... to percepcja. Samo w sobie daje satysfakcję, że moje działanie rzeczywiście osiągnęło swój cel.

Mimo że programista może sfałszować to zachowanie za pomocą podanych tutaj sugestii, postrzeganie nadal pozostaje, tzn. Aplikacja powinna całkowicie przestać działać (teraz) przez niezależne, zaufane i neutralne źródło (OS) na żądanie od użytkownika końcowego.


2
Dobrze. Dobry stary Windows Mobile oferował ten sam przycisk X, co komputery PC z systemem Windows, tyle że w rzeczywistości nie zamknął aplikacji, po prostu „zminimalizował” ją. Wielu użytkowników prawdopodobnie nigdy się nie dowiedziało, że aplikacja tak naprawdę nie zakończyła pracy. (Podejście to działało świetnie, chociaż jeśli korzystałeś z .NET Compact Framework, aplikacja nie została powiadomiona o tym, że tak się stało, a więc nie miała opcji zwolnienia zasobów ani faktycznego wyjścia.)
Qwertie

3
Naprawdę sprowadza się to do okłamania użytkowników, aby dać im ciepłe, rozmyte uczucie. Ostatecznie lepiej pozwolić, aby relikty przeszłości upadły na dalszy plan, aby nie stały się stałym elementem technologii. Mobilne i internetowe to nowe platformy i nie oczekuje się, że będą zachowywać się tak samo jak komputery stacjonarne. I przynajmniej anegdotycznie, decyzje dotyczące cyklu życia Androida wydają się być doceniane przez użytkowników: gdy moja największa aplikacja mija 2 lata, zauważyłem strumień wysychających żądań użytkowników końcowych, aby przyciski „wyjścia” wysychały w miarę przyzwyczajania się do nowa platforma.
Jon O

2
@Jon Co polecasz? Nie oferujesz opcji „wyjścia” nigdzie w aplikacji?
IgorGanapolsky

Cóż, gdy użytkownik poprosił o przycisk wyjścia, wyjaśniłbym im dokładnie, jak rzeczy działały inaczej niż na pulpicie (to samo wyjaśnienie, które podam im, gdy wspominają o zabójcach zadań). Teraz wydaje się, że informacje zostały przyłapane i nie otrzymuję już tych żądań. Zalecam więc wyjaśnić to kilka razy (być może wymyślić odpowiedź z puszki) i pominąć przycisk. Lub wstaw fałszywy przycisk wyjścia, który wyświetla okno dialogowe wyjaśniające, dlaczego nie ma już przycisków wyjścia. : D (Również w Androidzie 4+ użytkownik może przesunąć aplikację „wyłączoną” z ekranu wielozadaniowości, aby ją „zabić”.)
Jon O

3
Nie znalazłem też uzasadnienia wszystkich rad mówiących: „nie zabijaj procesu”. Moim zdaniem klient ma zawsze rację, więc co jest złego w zapewnianiu przycisku wyjścia po otrzymaniu prośby i „okłamywaniu użytkowników, aby dać im ciepłe, niewyraźne uczucie”, jeśli tego właśnie chcą? Po części chodzi o pisanie dobrych aplikacji. Większość użytkowników nie wie ani nie obchodzi, co naprawdę dzieje się pod maską, ale jeśli podoba Ci się twoja aplikacja i robi to, czego chce i oczekuje, wróci i kupi więcej aplikacji. Tego wszyscy chcemy, prawda? A może coś mi brakuje?
DDSports

37

Państwo może zamknąć, albo przez naciśnięcie Backprzycisku lub poprzez wywołanie finish()w twojej Activity. Wystarczy zadzwonić finish()z, MenuItemjeśli chcesz jawnie go zabić.

Romain nie twierdzi, że nie da się tego zrobić, tylko że jest to bezcelowe - użytkownicy nie muszą przejmować się rezygnacją lub zapisaniem swojej pracy, czy cokolwiek innego, ponieważ sposób działania cyklu życia aplikacji zachęca do pisania inteligentnego oprogramowania, które automatycznie zapisuje i przywraca jego stan bez względu na to, co się stanie.


5
Nie ma sensu, jeśli wypełnia cel, a w naszej aplikacji właśnie to robi. Na przykład chcemy sprawdzić aktualizacje przy wychodzeniu z aplikacji. Nie możemy wyjść z aplikacji, wtedy nie można dokonać aktualizacji. Niektóre komentarze sugerują, że naciśnięcie przycisku Wstecz wcale nie zabija aplikacji (patrz link w moim pytaniu powyżej).
Ted

2
Jak mówi Romain, nie tak działają podstawowe aplikacje. Jeśli więc użytkownicy są przyzwyczajeni do naciskania przycisku „Wstecz”, aby zamknąć aplikację, wydaje się prawdopodobne, że nadal będą to robić z Twoją aplikacją, zamiast jawnie wybierać opcję Zakończ? Możesz wykonać aktualizację przy starcie, onDestroy () lub przy użyciu powtarzającego się alarmu. Nie wydaje się, aby wymagało to uruchomienia przez użytkownika.
Christopher Orr,

1
Tom: Koduję dla Windows Mobile od prawie 5 lat. To jest telefon z „ograniczonymi zasobami”. Nie ma tam takiego zachowania i nie ma problemów z tym, że nie działa on w tym „starszym bracie”. „Prawdziwe aplikacje” = tam, gdzie programista ma o wiele większą kontrolę nad nim, tj. Rezygnuje, gdy usuwa się GUI itp.
Ted

1
Jay: ponieważ jeśli nadal jest w pamięci, nie mogę zaktualizować aplikacji. Nie można użyć plików delelte, prawda? Chcę aktualizować przy wyjściu, ponieważ nie możemy zmusić naszych użytkowników do aktualizacji przy starcie. Ma to związek z tym, jak działają i czego potrzebują. Wymuszanie aktualizacji na początku zmiany nie jest w porządku z różnych powodów. To trochę skomplikowane.
Ted

1
Jay: Nie, jak już powiedziałem, nie jest to aplikacja rynkowa i tak też nie będzie. Jest to bardzo wyspecjalizowana aplikacja, nieprzeznaczona do ogólnego użytku.
Ted

31

Ta debata sprowadza się do odwiecznego pytania, czy programiści wiedzą najlepiej, czy użytkownik wie najlepiej. Profesjonalni projektanci we wszystkich obszarach ludzkich czynników zmagają się z tym każdego dnia.

Ted zauważył, że jedną z najczęściej pobieranych aplikacji na rynku jest „App Killer”. Ludzie dostają trochę dodatkowej serotoniny, kiedy opuszczają aplikacje. Są do tego przyzwyczajeni z komputerem stacjonarnym / laptopem. Utrzymuje szybki ruch. Utrzymuje chłodzenie procesora i włączanie wentylatora. Zużywa mniej energii.

Jeśli weźmiesz pod uwagę, że urządzenie mobilne jest znacznie mniejszym statkiem, możesz szczególnie docenić ich zachętę do „wyrzucania za burtę tego, czego już nie potrzebujesz”. Teraz twórcy Androida przekonali się, że system operacyjny wie najlepiej, a zamknięcie aplikacji jest antyczne. Z całego serca to popieram.

Uważam jednak, że nie powinieneś frustrować użytkownika, nawet jeśli frustracja ta wynika z jego własnej niewiedzy. Z tego powodu dochodzę do wniosku, że posiadanie opcji „Wyjdź” to dobry projekt, nawet jeśli w większości jest to przycisk placebo, który robi jedynie zamknięcie Widoku.


8
Tak, przycisk „Wyjdź” jest naprawdę przyjazny dla użytkownika. W jaki inny sposób użytkownik mógłby zamknąć aplikację, jeśli ma w niej 5 czynności? Pewnie, że mogą naciskać wiele razy, ale nie sądzę, by im się podobało.
IgorGanapolsky

4
Tylko 5? Przeglądarka internetowa systemu Android 2.2 spędza kilka minut, dotykając przycisku Wstecz, aż w końcu wyjdę
Joe Plante

3
Zaczynam słuchać programistów Androida, gdy opracowują menedżera pamięci, który DZIAŁA. Począwszy od Froyo, działał bardzo słabo, zabijając losowe aplikacje, ponownie uruchamiając aplikacje, które nie muszą być (i nie mają intencji, aby je legalnie uruchomić) oraz OTOH, spowalniając do KOMPLETNEGO indeksowania, gdy pamięć osiągnie 50 MB wolnego miejsca.
DVK

10
Gdy Twoja religia mówi, że Android Task Killer jest „niepotrzebny”, ale użycie ATK do zabicia głupich zadań, które nie mają uruchomionego biznesu, zmienia system operacyjny z indeksowania z ~ 1-5% normalnej prędkości z powrotem do 100% normalnej prędkości ( mierzone) 100% czasu w tysiącach zastosowań ATK w ciągu 2 lat za każdym razem, gdy system osiąga
DVK

@JoePlante Możesz najpierw zamknąć wszystkie otwarte karty i okna, a następnie raz nacisnąć przycisk Wstecz, aby wyjść :) Przynajmniej na moim GS2.
dam

29

Ted, to, co próbujesz osiągnąć, może zostać zrobione, być może nie tak, jak teraz o tym myślisz.

Proponuję przeczytać o działaniach i usługach. Przestań używać terminu „aplikacja” i zacznij odnosić się do składników, tj. Działania, usługi. Myślę, że musisz tylko dowiedzieć się więcej o platformie Android; jest to zmiana sposobu myślenia w stosunku do standardowej aplikacji na PC. Fakt, że żaden z twoich postów nie zawiera słowa „Aktywność” (oprócz cytatu z FAQ, tj. Nie twoich słów) mówi mi, że musisz przeczytać więcej.


Przeczytałem większość rzeczy na android.com =) i mogę link do kilku moich pytań, w których mówię o działaniach, więc to nieprawda (np. Stackoverflow.com/questions/2032335/… lub stackoverflow.com/questions/ 2032335 /… itd ...) Mogę jednak spróbować jeszcze raz i spróbować stworzyć aplikację „who” jako Servce ...
Ted

4
Aplikacja może zawierać Usługi i Aktywności i wygląda na to, że Twoja aplikacja może potrzebować obu. Aktywność jest tylko częścią interfejsu użytkownika.
Aaron

23

Wpis na blogu Kiedy włączyć przycisk wyjścia w aplikacjach na Androida (Wskazówka: Nigdy) wyjaśnia to daleko, znacznie lepiej niż potrafię. Chciałbym, żeby każdy programista Androida już to przeczytał.

Fragmenty:

Z mojego doświadczenia wynika, że ​​[użytkownicy] naprawdę chcą: wynika, że Jednoznaczny sposób zagwarantowania, że ​​aplikacja przestanie zużywać zasoby (bateria, cykle procesora, transfer danych itp.).

Wielu użytkowników uważa, że ​​przycisk wyjścia implementuje ten wymóg i prosi o jego dodanie. Programiści, chcąc zadowolić swoich użytkowników, obowiązkowo je dodają. Niedługo potem oboje zawodzą.

  • W większości przypadków przycisk wyjścia po prostu wywołuje Activity.finish(). Jest to dokładnie równoważne naciśnięciu przycisku Wstecz. Dokładnie. Usługi nadal działają, a odpytywanie trwa. Użytkownicy mogą myśleć, że zabili aplikację, ale nie zrobili tego, a wkrótce będą jeszcze bardziej zirytowani.
  • Zachowanie wyjścia jest teraz niejednoznaczne. Czy przycisk wyjścia powinien po prostu zamknąć działanie, czy też powinien zatrzymać wszystkie powiązane usługi, odbiorniki i alarmy? Co należy Backzrobić Co się stanie, jeśli Homezamiast tego uderzą ? Co się stanie, jeśli Twoja aplikacja ma widżet? Czy przycisk wyjścia powinien powstrzymać to również od aktualizacji?

Rozwiązaniem jest, aby przycisk Wstecz zachowywał się tak, jak można się spodziewać po przycisku wyjścia. Co więcej, po prostu przestań zużywać zasoby, gdy aplikacja nie jest widoczna.

Śmiało i przeczytaj cały artykuł.


3
Wyjście i powrót nie zawsze są używane w tym samym celu. Weźmy na przykład Pandorę. Gdy wrócisz, aby wyjść z tej aplikacji, nie wychodzi ona z aplikacji (utrzymuje ją w tle jako usługa).
IgorGanapolsky

@IgorG. Aplikacja odtwarzacza muzyki wymaga przycisku „Stop”, aby zatrzymać odtwarzanie muzyki, a nie przycisku „Wyjdź”, aby wyjść z aplikacji.
Dheeraj Vepakomma,

Czy kiedykolwiek używałeś Pandora, iHeartRadio, Spotify, Jango i innych aplikacji do strumieniowego przesyłania muzyki? Wszystkie mają przycisk wyjścia. Zatrzymywanie odtwarzania muzyki NIE JEST TAKIM SAMEM, jak zamknięcie aplikacji. Zwłaszcza jeśli masz usługę uruchomioną na pasku powiadomień.
IgorGanapolsky

2
Mityczni czy nie, prymitywni użytkownicy czy nie, ale prawie każde oprogramowanie interfejsu użytkownika, jakie kiedykolwiek napisano - na dowolnej platformie i systemie operacyjnym - implementuje przycisk wyjścia / zamknięcia / wyjścia. Jak inaczej byś to wdrożył?
IgorGanapolsky

3
@ DheerajV.S., Po prostu przestać zużywać zasoby, gdy aplikacja nie jest widoczna? Zła rada. Bardzo. Bardzo x99. Ilekroć próbuję przesłać sobie zdjęcie e-mailem, muszę zachować widoczność aplikacji przez pełne 5 minut, ponieważ jeśli zminimalizuję, przestanie on wysyłać zdjęcie. Zgadza się, nie mogę korzystać z telefonu przez pełne 5 minut tylko dlatego, że niektórzy programiści uważają, że aplikacje powinny działać tylko wtedy, gdy są widoczne. Teraz wyobraź sobie wysyłanie większego pliku, takiego jak wideo .....
Pacerier,

21

Odpowiedź: (Romain Guy): Użytkownik nie, system obsługuje to automatycznie. Do tego właśnie służy cykl życia aktywności (szczególnie onPause / onStop / onDestroy). Bez względu na to, co robisz, nie umieszczaj przycisku aplikacji „wyjdź” lub „wyjdź”. Jest to bezużyteczne w przypadku modelu aplikacji Androida. Jest to również sprzeczne z działaniem podstawowych aplikacji.

1: Całkowite zamknięcie aplikacji może być zasadniczo nieobowiązkowe, ale nie jest bezużyteczne. Co jeśli system Windows nie miał opcji wyjścia? System byłby bardzo powolny, ponieważ pamięć była pełna, a system operacyjny musiał zgadywać, z których programów korzystałeś. Nie obchodzi mnie, co mówią Romain Guy, a nawet Larry Page i Sergey Brin - są to niepodważalne fakty: systemy działają wolniej, gdy muszą zabijać zadania, aby odzyskać pamięć, zanim będzie można uruchomić nową aplikację. Po prostu nie możesz mi powiedzieć, że zabicie aplikacji nie zajmuje czasu! Nawet światło z odległych gwiazd potrwać ... Nie jest pewne zastosowanie w pozwalając użytkownikowi w pełni bliskich aplikacji.

2: W przeciwieństwie do podstawowych aplikacji? Co to ma znaczyć? Kiedy skończyłem na razie uruchamiać aplikację, nie wykonuje już żadnej pracy ... Po prostu czeka, aż zabije ją system operacyjny, gdy potrzebna jest jej pamięć.

Podsumowując, istnieje wyraźna różnica między minimalizacją a wyjściem, i żadna szczypta nie trafia dobrze w drugą stronę. Czy zostawiamy śrubokręt w każdej śrubie? Czy klucz w każdych drzwiach? Czy zostawiamy wszystkie nasze urządzenia na wysokości, dopóki nie zadziała wyłącznik i musimy włączyć inne urządzenie? Czy zostawiamy zmywarkę pełną naczyń i za każdym razem wyjmujemy tylko tyle, aby zrobić miejsce dla nowych brudnych naczyń? Czy zostawiamy wszystkie samochody jeżdżące na podjeździe, aż - och, nieważne.

Jeśli użytkownik chce zminimalizować aplikację, najlepiej jest ją zminimalizować. Jeśli użytkownik chce wyjść z aplikacji, najlepiej jest wyjść.

Czy to marszczy brwi? To widok Androida - marszczą brwi. I wielu wielu niezależnych początkujących programistów Androida marszczy brwi.

Ale jeśli chodzi o to, jest dobre i złe kodowanie. Istnieją dobre modele przepływu programów i złe modele przepływu programów.

Pozostawienie programów w pamięci, gdy użytkownik wie, że zostały wykonane, po prostu nie jest dobrym przebiegiem programu. Służy to absolutnie bezcelowi i spowalnia rzeczy podczas uruchamiania nowych aplikacji lub uruchamiania aplikacji, które przydzielają więcej pamięci.

To trochę jak twój samochód: zdarza się, że zostawiasz go w ruchu, np. Zatrzymujesz się na światłach stopu, a może przejeżdżasz przez fast food lub zatrzymujesz się w bankomacie. Ale są też inne sytuacje, w których chcesz to wyłączyć - na przykład, gdy wracasz do pracy, do sklepu spożywczego lub nawet do domu.

Podobnie, jeśli grasz w grę, a telefon dzwoni, tak. Zatrzymaj grę i utrzymuj ją. Ale jeśli użytkownik skończy z grą przez jakiś czas, to z całą pewnością pozwól mu wyjść.

Przycisk wyjścia w niektórych aplikacjach powinien być bardziej widoczny niż inne. Na przykład gry lub programy, w których użytkownik może chcieć całkowicie wyjść, powinny mieć oczywiste wyjście. Inne programy, na przykład programy poczty e-mail, w których wyjście jest mało prawdopodobne (aby mógł nadal sprawdzać pocztę e-mail) - programy te nie powinny marnować pierwotnej przestrzeni wejściowej ekranu sterowania z opcją wyjścia, ale dla dobrego przebiegu programu, to powinien mieć opcję wyjścia. Co się stanie, jeśli ktoś zdecyduje, że nie chce, aby jego program pocztowy próbował sprawdzić pocztę e-mail, gdy znajduje się w słabym zasięgu, a może podczas rozmowy przez Skype'a? Pozwól im opuścić program pocztowy, jeśli chcą!

Zawieszanie i wychodzenie to dwa ważne zadania, które nie spełniają roli drugiego.


2
„Jeśli użytkownik chce zminimalizować aplikację, najlepszą rzeczą jest ją zminimalizować. Jeśli użytkownik chce zamknąć aplikację, to najlepiej jest, aby ją zamknąć”. - Jest coś (w oparciu o więcej niż dziesięć lat doświadczenia): użytkownicy rzadko wiedzą, czego chcą. Jeśli im nie pomożesz, będziesz musiał to zmienić. O powyższych próbkach: dam ci inną próbkę: pracujesz nad samochodem i masz pod ręką stolik na różne rzeczy. Czy zawsze odkładasz na właściwe miejsce wszystkie niezbędne narzędzia do szafki lub trzymasz najczęściej używane pod ręką? A po prostu odłożyć dużego, spóźnionego, aby mieć miejsce na nowe?
HoGo

4
HoGo, dzięki za komentarz. Oczywiście się nie zgadzam. W szczególności, najlepiej jak potrafię powiedzieć, twój pogląd jest taki, że ponieważ niektórzy użytkownicy nie wiedzą, co powinni robić, dlatego nie pozwól żadnym użytkownikom robić tego, co powinni, nawet tym, którzy wiedzą, co powinni robić. Jeśli Android miał sposób dokładnie wiedzieć, czy powinien zamknąć aplikację zamiast ją minimalizować, to dobrze. Ale tak się nie dzieje, a zmuszanie wszystkich użytkowników do życia z minimalizacją, gdy chcą wyjść, prowadzi do niskiej wydajności urządzenia.
Jesse Gordon

Chodzi o to, że system wie, że kiedy uruchomisz jedną aplikację i nie ma pamięci, powinna zabić ostatnią. Użytkownik nie powinien tego wiedzieć. Potrzebujesz tego tylko dlatego, że jesteś człowiekiem, który lubi poczucie kontroli, głupią pamięć mięśni, nawet bezcelową kontrolę zamykania programów. Komputery zostały wymyślone do automatyzacji. Chciałbym, aby Windows działał jak Android i po prostu automatycznie się zamykał, ale muszę pamiętać, aby zapisać i wyjść, to głupie, dlaczego miałbym to robić? komputery powinny zarządzać swoją pamięcią, mam inne rzeczy do zarządzania.
Luiz Felipe

Właściwie nie zamykam programów na komputerze z systemem Windows, mam 32 GB pamięci RAM, po prostu zostawiam wszystko uruchomione, zamykam je po zakończeniu pracy. Po co zamykać program, aby otworzyć go ponownie 5 minut później, nie ma to sensu. Pomyśl o dużym projekcie C ++, który zajmuje 2 minuty, aby stać się responsywnym, po prostu zostawiam Visual Studio otwarte na zawsze. I spodziewam się, że nie zawiesi się również po 15 dniach od otwarcia (i tak, używam do tego pamięci ECC).
Luiz Felipe

Analogia do warsztatu jest dobra, zostawiam najczęściej używane narzędzia na biurku, nie wybieram narzędzia, nie używam go i odkładam za każdym razem. Poza tym nie zaczynam dnia, włączam komputer, czekam na uruchomienie, otwieram IDE, cokolwiek. Po prostu zostawiam włączony, nowoczesny komputer może pracować bezczynnie przy 40 W, po co go zamykać? również zużywa mniej elementów (brak prądu rozruchowego, EE to wie :))
Luiz Felipe

19

Myślę, że chodzi o to, że nie ma potrzeby zamykania aplikacji, chyba że masz wadliwe oprogramowanie. Android zamyka aplikację, gdy użytkownik jej nie używa, a urządzenie potrzebuje więcej pamięci. Jeśli masz aplikację, która musi uruchamiać usługę w tle, prawdopodobnie będziesz chciał ją wyłączyć.

Na przykład Google Listen kontynuuje odtwarzanie podcastu, gdy aplikacja nie jest widoczna. Ale zawsze jest przycisk pauzy, aby wyłączyć podcast, gdy użytkownik skończy z nim. Jeśli dobrze pamiętam, Słuchaj, nawet wstawia skrót na pasku powiadomień, dzięki czemu zawsze możesz szybko przejść do przycisku pauzy. Innym przykładem jest aplikacja, na przykład aplikacja Twittera, która stale odpytuje usługę w Internecie. Tego rodzaju aplikacje powinny naprawdę pozwolić użytkownikowi wybrać, jak często odpytywać serwer, a nawet czy odpytywać w wątku w tle.

Jeśli potrzebujesz kodu działającego przy wyjściu, możesz zastąpić odpowiednio onPause (), onStop () lub onDestroy (). http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle


5
Wraz z innymi bałaganami, które odkryłem, myślę, że opracowanie naszej aplikacji na Androida nie nastąpi. To za dużo „starszego brata” - wszystko dzieje się, gdzie Android mówi mi, która aplikacja powinna działać, czy nie. Ja jako programista powinienem mieć ten wybór, a nie Google lub Android = (
Ted

3
Twoje działania - aktywny interfejs użytkownika - znikają, gdy na wierzchu pojawi się kolejna aplikacja lub cofniesz się lub cokolwiek innego. Użytkownik nie wchodzi w interakcję z nim, więc najbezpieczniej jest zapisać stan na wypadek, gdyby użytkownik nie wracał przez długi czas i tak dalej, jak wiadomo. Nic nie stoi na przeszkodzie, abyś pisał Servicedalej, aby kontynuować ciągłą pracę w tle, na przykład odbieranie wypychanych danych lub cokolwiek innego. Google Talk nie przestaje działać, gdy używasz innej aplikacji. To samo z odtwarzaczem muzyki. Spójrz na inne aplikacje i jak działają.
Christopher Orr,

3
Powinieneś być w stanie zapisać poświadczenia, aby użytkownicy nie musieli się logować za każdym razem, gdy otrzymają połączenie telefoniczne lub odejdą od Twojej aplikacji. Polecam przyjrzeć się cyklowi życia Androida. Gdy aplikacja zostanie wstrzymana, zatrzymana lub zniszczona, możesz zapisać wszystkie odpowiednie dane, aby po ponownym otwarciu aplikacja wyglądała tak, jak ją opuściła. Użytkownik nie musi nawet wiedzieć, że aplikacja została kiedykolwiek zatrzymana.
Jay Askren,

1
Mogę sobie wyobrazić, że użytkownik może chcieć zamknąć niektóre naprawdę wymagające aplikacje. Może powinien po prostu ograniczyć zużycie zasobów, gdy jest wstrzymany, ale nie zawsze jest to możliwe
Casebash

1
To pytanie wciąż żyje Rozumiem, 4 lata po tym, jak to wychowywałem =) Rzeczywiście uruchomiłem go jako usługę w tle, ale dodałem przycisk wyjścia, ponieważ nadal czuję - 4 lata później - to jest konieczne i ważne. I widzę coraz więcej aplikacji, które również to mają (na przykład Skype).
Ted

19

Jeśli nie jesteś w stanie pojąć, jak utrwalić dane / połączenia (a tym samym swoją „aplikację”), nie będziesz w stanie zrobić tego, co „potrzebujesz”, aby zrobić z Androidem.

Ci, którzy pobierają te urocze małe App Killers, zwykle stwierdzają, że nie pomagają w pracy na baterii ani w zużyciu pamięci, ale utrudniają systemowi wydajne zarządzanie pamięcią ...

http://android-developers.blogspot.com/2010/04/multitasking-android-way.html


Podczas gdy mówimy o zabójcach zadań, kilka dni temu na Androida reddit pojawił się bardzo pouczający post. Chodzi o to, ostrożnie używaj zabójców zadań, w przeciwnym razie może to popsuć
Neil Traft

@ Neil Traft, uważam, że komentarze do postu są bardzo pouczające.
Przedstawiciele

3
@ Dan, jak to możliwe, że nawet w pełni wychodzę z aplikacji, z którą skończyłem na tydzień, utrudniam systemowi Android Android jego pracę? Więc jest więcej wolnej pamięci. To nie może utrudniać Androida! Jednak z pewnością może to przyspieszyć później! Jeśli wiem, że skończyłem z aplikacją przez jakiś czas, nie ma to absolutnie żadnego celu. Zajmuje tylko pamięć, a wcześniej czy później uruchomię nową aplikację, a system operacyjny będzie miał dodatkowe opóźnienie, ponieważ musi zabić niektóre aplikacje, o których wiedziałem, że TYGODNIE temu skończyłem.
Jesse Gordon

@Jesse Gordon, czy obserwowałeś rzeczywiste procesy po tym, jak zabiłeś aplikację? Zostają ponownie uruchomione, system operacyjny zakłada, że ​​wystąpił problem ... System operacyjny zabije aplikacje, gdy potrzebuje pamięci. Czy w ogóle czytałeś coś zamieszczonego w artykułach wspomnianych tutaj?
Dan

@ Dan, Aby pomyśleć, że Android zrobiłby coś takiego ... naprawdę potrzebuje poważnej reedukacji w myciu bieli.
Pacerier

18

Rozważę przeczytanie „Rozwoju aplikacji bezprzewodowych dla Androida” opublikowanego przez Addison-Wesley. Właśnie kończę i jest to BARDZO dokładne.

Wygląda na to, że masz pewne podstawowe nieporozumienia dotyczące platformy Android. Ja również byłem trochę sfrustrowany cyklem życia aplikacji na Androida, ale po lepszym zrozumieniu zacząłem naprawdę podobać się temu podejściu. Ta książka odpowie na wszystkie twoje pytania i wiele więcej. To naprawdę najlepszy zasób, jaki znalazłem dla nowych programistów Androida.

Myślę też, że musisz puścić port liniowy dla istniejącej aplikacji. Aby przenieść aplikację na platformę Android, niektóre elementy aplikacji zmienią się. Zastosowany cykl życia aplikacji jest konieczny, ponieważ urządzenia mobilne mają bardzo ograniczone zasoby w stosunku do systemów stacjonarnych i umożliwiają urządzeniom z Androidem uruchamianie kilku aplikacji w uporządkowany i świadomy sposób. Przeanalizuj nieco platformę i myślę, że zdasz sobie sprawę, że to, co chcesz zrobić, jest całkowicie wykonalne. Powodzenia.

Nawiasem mówiąc, nie jestem w żaden sposób związany z Addison-Wesley ani żadną osobą lub organizacją związaną z tą książką. Po ponownym przeczytaniu mojego postu czuję, że wyszedłem na trochę fanowskiego. Po prostu bardzo mi się podobało i uważam to za bardzo pomocne. :)


2
Dzięki za poradę. Spojrzę na to, jeśli będę mógł i jeśli zdecyduję się przenieść na port Androida. Wystarczy jednak powtórzyć: nasi użytkownicy nie są bardzo aktualni, jeśli chodzi o komputery. Będę dla nich bardzo trudny w użyciu na przykład paska powiadomień w systemie Android. Zbyt małe (mają DUŻE palce hehe). To dla nich inny świat, dlatego musimy zachować prostotę i nie mieć opcji dla użytkownika. Z myślą o tym zbudowaliśmy nasze rozwiązanie .NET - nie daj im wyboru =)
Ted

Słysze to. Musisz założyć, że większość użytkowników nie jest zbyt inteligentna technicznie.
Andy

8
Mam już dość mantry o tym, jak mało „zasobów” ma urządzenie mobilne. Obudź się, działają na częstotliwości ponad 500 MHz i mają mnóstwo pamięci. Mój stary Dell Axim miał 128 MB pamięci RAM. Obecne urządzenia mają zwykle ponad 512 RAM i działają na 1GHZ! To 10 razy więcej niż moje stare Pentium 90 MHz i nie słyszałem ppl mówiącego „bardzo ograniczone zasoby” to i tamto. Czas się obudzić i poczuć zapach kawy - jesteśmy teraz w 2010 roku, a nie w latach 80.
Ted

16

Niemal w 99% przypadków aplikacja Android nie musi przejmować własnego cyklu życia. W większości przypadków sprowadza się to do lepszego planowania lub inteligentniejszego projektowania aplikacji. Na przykład raczej zbuduj usługę wewnętrzną (nie eksportowaną) do obsługi pobrań itp. Lub zaprojektuj działania i zadania wokół przepływu pracy użytkownika.

Ale powiedziawszy to, tam gdzie jest wola, istnieje sposób. Android zapewnia - za pośrednictwem klasy android.os.Process - znacznie lepszy interfejs API niż Java do kontrolowania podstawowego procesu. I w przeciwieństwie do Javy, nie traktuje programisty jak kretyna, ukrywając wszystko za prostym wywołaniem java.lang.System.exit ().

Jak więc poprosić aplikację o popełnienie samobójstwa w systemie Android? Sztuczka jest prosta:

Utwórz własną klasę aplikacji na Androida, dziedzicząc po standardowej klasie android.app.Application (pamiętaj, aby zadeklarować ją w pliku AndroidManifest.xml).

Zastąp metodę onCreate () i zapisz identyfikator procesu, który uruchomił aplikację:

this.pid = android.os.Process.myPid(); // Save for later use.

Teraz, aby zabić aplikację, podaj metodę kill ():

android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);

Teraz, gdy potrzebujesz popełnić samobójstwo, po prostu napisz kontekst aplikacji i wywołaj metodę kill!

((MySuicidalApp) context.getApplicationContext()).kill()

Pamiętaj tylko, że ze względu na zasady zarządzania procesami w systemie Android, szczególnie związane z usługami, system Android może po prostu zrestartować usługę (zobacz Nie powinieneś używać funkcji zabijania zadań w systemie Android ).


tak, przyszedłem tutaj tylko dlatego, że chciałem zamknąć aplikację w jednej sytuacji, która ma sens, pamięć podręczna danych OBB jest uszkodzona i muszę ponownie uruchomić całą aplikację
Luiz Felipe

14

Gdy tworzę aplikację na Androida, widzę to w następujący sposób:

  • Pracujesz z aplikacją
  • Telefon zadzwonił
  • Ty odbierasz połączenie
  • Po zakończeniu rozmowy wrócisz do aplikacji w tym samym miejscu, w którym byłeś

Aby to zrobić, potrzebujesz tylko Backprzycisku lub Homeprzycisku telefonu (przez krótkie lub długie naciśnięcie) i paska powiadomień.

Kiedy wychodzę z aplikacji, używam Backprzycisku tylko do momentu, gdy go nie opuszczę lub Homeprzycisku.

Tak myślę, że w ten sposób powstaje większość aplikacji. Ale jeśli potrzebuję sesji lub połączenia, wyjaśniłem to użytkownikowi przyciskiem logowania / wylogowania i powiadomieniem (pasek tytułu lub cokolwiek innego). Jest to raczej inny styl niż aplikacja w stylu „wyjścia”.

Na PC masz pulpit z wieloma GUI, a na Androidzie oczywiście masz wiele zadań, ale wyświetlasz tylko jedną aplikację na raz (nie rozważam tutaj widżetów ^^). A na telefonie komórkowym możesz w każdej chwili otrzymać powiadomienie o czymś ważniejszym niż to, co robisz.

Zatem cała koncepcja aplikacji opiera się na czymś innym, co „wchodzi do aplikacji - praca - wychodzi z aplikacji”.


12

Hmmmm ...

Myślę, że po prostu nie widzisz aplikacji na Androida we właściwy sposób. Z łatwością możesz zrobić coś prawie tak, jak chcesz:

  • Czy działania aplikacji zapisują / przywracają stan, tak jak jest to zalecane w dokumentacji cyklu życia dewelopera.

  • Jeśli konieczne jest zalogowanie się na etapie przywracania (brak dostępnych danych logowania / sesji), zrób to.

  • W końcu dodaj przycisk / menu / limit czasu, w którym to przypadku zrobisz to finish()bez zapisywania loginu i innych informacji o sesji, co pośrednio zakończy sesję aplikacji: więc jeśli aplikacja zostanie uruchomiona / przeniesiona ponownie, rozpocznie nową sesję.

W ten sposób nie obchodzi Cię, czy aplikacja zostanie naprawdę usunięta z pamięci, czy nie.

Jeśli naprawdę chcesz go usunąć z pamięci (to jest zalecane, a przy okazji w jakim celu?), Można go zabić warunkowo na koniec onDestroy()z java.lang.System.exit(0)(a może restartPackage(..)?). Oczywiście rób to tylko w przypadku, gdy chcesz „naprawdę zakończyć aplikację”, ponieważ onDestroy()jest to część normalnego cyklu życia działań, a wcale nie koniec aplikacji.


11

Ponieważ aplikacja w kontekście Androida to tylko kilka niejasno powiązanych działań, zamknięcie aplikacji nie ma większego sensu. Możesz zakończyć () działanie, a widok poprzedniego działania na stosie działań zostanie narysowany.


2
W niektórych sytuacjach zamknięcie aplikacji może mieć sens. Jeśli jest to program, z którego korzystasz kilka razy w miesiącu przez kilka minut, niewątpliwą korzyścią jest pełne zamknięcie aplikacji. Korzyścią jest to, że system operacyjny nie będzie musiał tracić czasu na zamknięcie aplikacji tydzień później, gdy zabraknie pamięci, a telefon zadzwoni, a ty naciśniesz przycisk odbierania i czekasz, aż Android zwolni trochę pamięci na przykład możesz odebrać połączenie. A może masz wiadomość e-mail i chcesz ją przeczytać - każda aplikacja, która potrzebuje więcej pamięci, uruchomi się szybciej, jeśli system operacyjny najpierw jej nie zwolni.
Jesse Gordon

3
To, co powiedział @JesseGordon, i jeszcze jeden aspekt tego powodu, dla którego rezygnacja ma sens: jeśli nie wyjdę z aplikacji wymagającej dużych zasobów, wiem, że nie będę jej używać przez miesiąc, system operacyjny czasami niesłusznie zabije inną aplikację gdy zasoby stają się rzadkie, pozostawiając działającą tę bezużyteczną aplikację dla zasobów… co sprawia, że ​​wznawianie działania innej aplikacji trwa dłużej niż powinno.
Don Hatch

10

Zgadzam się z Tedem. Rozumiem, że zamknięcie aplikacji nie jest „sposobem na Androida”, ale nie wydaje się, że należy to wykluczyć. Oto trzy powody, dla których możesz chcieć prawdziwego wyjścia z aplikacji (nie tylko działania):

  1. Użytkownik może chcieć mieć kontrolę nad tym, która aplikacja zostanie zabita w przypadku braku pamięci. Jeśli w tle jest uruchomiona ważna aplikacja A, możesz zamknąć aplikację B po jej zakończeniu, aby aplikacja A nie została zabita przez system operacyjny.

  2. Jeśli twoja aplikacja ma wrażliwe dane buforowane w pamięci, możesz chcieć ją zabić, aby wirus / robak / nieuczciwa aplikacja nie mogła się do niej dostać. Wiem, że model bezpieczeństwa ma temu zapobiec, ale na wszelki wypadek ...

  3. Jeśli aplikacja korzysta z zasobów (takich jak sieć, procesor, czujniki itp.), Które mogłyby mieć negatywny wpływ na telefon, wówczas jednym ze sposobów zapewnienia, że ​​zasoby te zostaną zwolnione, jest zamknięcie aplikacji. Rozumiem, że dobrze działające aplikacje powinny zwalniać zasoby, gdy nie są potrzebne. Ale znowu wyjście z aplikacji wydaje się rozsądnym sposobem na zapewnienie tego.


6
Jak myślisz, co reprezentuje „aplikację”? Jeśli otworzę aplikację Facebook i ustawię nowe zdjęcie profilowe - uruchomią się moje aplikacje aparatu lub galerii. Jako użytkownik wciąż wykonuję to samo zadanie (używając Facebooka). Jeśli następnie zdecyduję się zamknąć Facebooka, moje aplikacje aparatu i galerii również muszą się zamknąć (ponieważ są to działania uruchomione z Facebooka) ... Co jeśli byłbym w trakcie edycji niektórych innych zdjęć i chciałem tylko zamknąć Facebooka ? Przesunąłbyś problem na potencjalną utratę danych.
seanhodges

Cóż, nie sądzę, że może to sięgać aż do utraty danych. Jeśli masz działanie innej firmy działające w tym samym zadaniu, co własne działanie, a Twoja własność to ta z przyciskiem wyjścia, użytkownik musi przejść finish()do działania strony trzeciej, zanim będzie mógł nacisnąć przycisk wyjścia. W tym czasie działalność strony trzeciej powinna zapisywać wszelkie niezapisane informacje. Nie sądzę, że możesz użyć przełącznika aplikacji, aby powrócić do działania przycisku wyjścia, chyba że działa on w osobnym zadaniu. A jeśli jest to osobne zadanie, jest to osobny proces i dlatego nie zostanie zabity przez przycisk wyjścia.
Neil Traft

2
1. Myślę, że 99,99% użytkowników Androida nie powinno martwić się tym, jak system operacyjny zarządza aplikacjami za zasłonami. Reszta to maniacy i znajdą zaawansowane narzędzia, dzięki którym system będzie zachowywał się dokładnie tak, jak tego chce. 2. Zawsze możesz zwolnić dane wrażliwe, gdy aktywność zostanie wstrzymana lub zatrzymana. 3. Tak jak powyżej, zasoby można zwolnić w metodach wywołania zwrotnego cyklu życia. Po wznowieniu działania zasoby można ponownie przydzielić.
Zsolt Török

4
Myślę, że to dość interesujące, że tak wielu użytkowników Androida instaluje „Advanced Task Killer”, aplikację, która zamyka inne aplikacje, ponieważ zwykle nie możesz tego zrobić samodzielnie. Cały czas go używam. Zamykanie aplikacji nie jest czymś, bez czego nie można się obejść.
Ted

2
@ ZsoltTörök, 99,99% ludzi ma do czynienia z powolnymi komputerami / telefonami i są zmuszeni do wyboru, aby martwić się tym, jak system operacyjny zarządza aplikacjami za zasłonami.
Pacerier

10

Jądro Linuksa ma funkcję o nazwie Zabójca braku pamięci (jak wspomniano powyżej, zasady można konfigurować na poziomie przestrzeni użytkownika, a jądro nie jest optymalne, ale nie jest niepotrzebne).

I jest intensywnie wykorzystywany przez Androida:

Niektóre aplikacje przestrzeni użytkownika są dostępne, aby pomóc w tych aplikacjach do zabijania, na przykład:


9

Najwyraźniej znalazłeś pożądaną odpowiedź w poleceniu finish (). To nie usunie Twojej aplikacji z pamięci, ale Android zrobi to za każdym razem, gdy potrzebuje zasobów, więc nie ma znaczenia, że ​​nie zrobisz tego wprost.

Dodałbym tylko, że w celu uzyskania pełnego efektu, jaki zazwyczaj miałoby wyjście aplikacji, chciałbyś zresetować stan aplikacji do tego, jaki jest normalnie w momencie pierwszego uruchomienia po uruchomieniu urządzenia, tuż przed do wywoływania zakończenia () we wszystkich twoich działaniach. W ten sposób, jeśli użytkownik ponownie wybierze aplikację, będzie wyglądać na uruchomioną „świeżo”, bez żadnego stanu pozostałego od momentu przed symulowanym „wyjściem”.

Jeśli są jakieś specjalne akcje, które powinny wystąpić tylko przy „wyjściu”, takie jak zapisanie pracy użytkownika lub cokolwiek innego, możesz je wykonać przed częścią ponownej inicjalizacji powyższej procedury.

Takie podejście pozwala osiągnąć cel polegający na wydaniu polecenia „exit” bez naruszania filozofii Androida polegającej na pozostawieniu zarządzania zasobami systemu operacyjnego, w tym zamykania aplikacji, w ręce systemu operacyjnego.

Osobiście nie użyłbym tego podejścia, ponieważ użytkownicy Androida oczekują, że aplikacja zachowa ciągłość, gdy ją odwiedzą, a więc nie są przyzwyczajeni do sposobu „wychodzenia” z aplikacji. Zamiast tego wspierałbym funkcję „wyczyść”, którą użytkownik może wywołać, aby zresetować aplikację do domyślnego stanu początkowego, bez konieczności „pozostawiania” jej w tym procesie.

Jedynym wyjątkiem jest sytuacja, gdy użytkownik wciśnie przycisk Wstecz wystarczającą liczbę razy, aby spowodować zamknięcie aplikacji. W takiej sytuacji użytkownik nie oczekuje, że stan zostanie zapisany (a jeśli w aplikacji występuje niezapisany stan, to jako programista powinien mieć kod obsługujący przycisk Wstecz, który wykrywa niezapisane dane, oraz monituje użytkownika o zapisanie go w SharedPreferences lub w pliku lub na innym nieulotnym nośniku).

Odnośnie system.exit (0):

Jeśli zdecydujesz się użyć system.exit (0), aby zamknąć aplikację z grubiańską ostatecznością (np. W wyniku ostatecznego naciśnięcia przycisku Wstecz), to ostrzegłbym cię, że chociaż dla mnie to „działa”, a w niektórych przypadki to jedyny sposób, w jaki udało mi się zamknąć aplikację bez śladu, jest jedna drobna usterka występująca w Jelly Bean, gdy używasz tego podejścia.

W szczególności, jeśli użyjesz listy Ostatnie aplikacje, aby otworzyć aplikację, a następnie użyjesz przycisku Wstecz, aby zamknąć aplikację (z tym zamknięciem zaimplementowanym przez system.exit (0)), lista Najnowsze aplikacje będzie ponownie widoczna, ponieważ będzie nigdy nie były zamknięte. Jeśli następnie dotknij wpisu Twojej aplikacji w tym liście, aby go uruchomić po raz drugi z tego samego, już otwarte, ostatnie listy Apps, nie będzie żadnej reakcji.

Podejrzewam, że przyczyną tego jest to, że lista ostatnio używanych aplikacji zawiera odniesienie do Twojej aplikacji, która przestała działać z powodu zamknięcia aplikacji za pomocą system.exit (0). Bardziej cywilizowane zamknięcie Twojej aplikacji za pomocą metody finish () mogło poinformować system operacyjny w sposób, który pozwoliłby mu odświeżyć listę ostatnich aplikacji, ale system.exit (0) najwyraźniej tego nie robi.

Sam w sobie nie jest to duży problem, ponieważ bardzo niewiele osób otworzy aplikację z ostatnich aplikacji, a następnie ją zamknie, a następnie natychmiast ponownie otworzy z tej samej listy ostatnich aplikacji. A jeśli stukną przycisk Początek, a następnie ponownie otworzą listę Najnowsze aplikacje, pozycja Twojej aplikacji będzie tam i będzie w pełni funkcjonalna. Ale myślę, że pokazuje, że użycie system.exit (0) może zakłócać prawidłową komunikację między twoją aplikacją a systemem operacyjnym, a to sugeruje, że mogą istnieć inne, poważniejsze, być może subtelne, konsekwencje zastosowania tego podejścia.


Być może mógłbyś usunąć ostatni wpis aplikacji przed wywołaniem zakończenia ()? Spróbuję to, kiedy pozwoli na to czas. Mam usługę pierwszego planu z małym działaniem programu uruchamiającego. Ponieważ Aktywność jest bardzo mała, nie jest to wielka sprawa, jeśli nie zostanie zabita i pochowana, ale rozsądnie jest powiedzieć Androidowi, że może to zrobić przed resztą, jeśli to możliwe.
nsandersen

9

Mam nadzieję, że z czasem wszystko się zmieni. Użytkownik powinien mieć możliwość zabicia aplikacji lub procesu, jeśli proces aplikacji jest poprawnie piaskownicą systemu operacyjnego. Istnieje pogląd, że aplikacje powinny być pisane idealnie, w przeciwnym razie użytkownik będzie korzystał tylko z aplikacji zgodnych ze wszystkimi zaleceniami SDK. Myślę, że to duże zamówienie.


Wiem. Produkty Apple są dobre dla niektórych konsumentów. Nie są dobre dla programistów. System operacyjny Android ma pełny potencjał, by stać się jak „system operacyjny Windows na świecie PC” dla telefonów komórkowych. może być jeszcze lepiej. Jest już bardziej otwarty niż okna świata PC, ale nie pozwala nam napisać menedżera zadań.
dipu

7

Istnieje (stosunkowo) prosta konstrukcja, która pozwoli ci obejść zagadkę „wyjścia”. Spraw, aby Twoja aplikacja miała stan „podstawowy” (działanie), który jest tylko pustym ekranem. Przy pierwszym utworzeniu działania możesz uruchomić inne działanie, w którym znajduje się główna funkcjonalność aplikacji. „Wyjścia” można następnie dokonać, kończąc () drugie działanie i wracając do podstawy pustego ekranu. System operacyjny może przechowywać ten pusty ekran w pamięci tak długo, jak chce ...

W gruncie rzeczy, ponieważ nie możesz wyjść z systemu operacyjnego, po prostu przekształcasz się we własną stworzoną nicość.


2
Dobry pomysł. Jednak nawet zakończenie działania (lub usługi) nie zatrzymuje systemu operacyjnego. O nie, nawet po wykonaniu onDestroy wszystkie zmienne i takie tam są. Właśnie zobaczyłem, że w służbie wszystko jest takie samo, mimo że onDestroy został nazwany ...
Ted

2
... i dlatego System.exit (0) pomógł =)
Ted

7

Bez funkcji wyjścia dla programisty aplikacji w celu zabicia własnej aplikacji jest to bardzo zły projekt.

Moja aplikacja musi pozwalać użytkownikowi dynamicznie zmieniać dane dynamicznie podczas działania, a użytkownik musi zrestartować moją aplikację, aby uzyskać efekt zmiany, ale Android sam nie zezwolił na ponowne uruchomienie aplikacji. System operacyjny Android ma bardzo zły cykl życia aplikacji.


9
public void appRestart () {Intent i = new Intent (getBaseContext (), MyActivity.class); i.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity (i); }
androidworkz

2
Powyższy kod komentarza naprawdę działa dobrze. Przynajmniej możesz przejść do pierwszej aktywności zamiast całkowitego wyjścia z aplikacji. :)
Harpreet

7

Aby zamknąć aplikację w dowolnym momencie, użyj FLAG_ACTIVITY_CLEAR_TOPflagi w polu Cel, a następniesystem.exit();

Lub istnieje podobny sposób, ale bez, system.exit()gdy chcesz wyjść, wywołaj tę metodę:

public void exit() {
    startActivity(new Intent(this, HomeActivity.class).
    setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
}

HomeActivity.onCreate()Dodaj swój kod

protected void onCreate(Bundle savedInstanceState) {
    if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
            finish();
        }
    }
......................

Będzie to działać bez przerywania cyklu życia Androida.


7

Przede wszystkim nigdy nigdy nie używaj System.exit (0). To tak, jakby ktoś spał i uderzył go w głowę!

Po drugie: mam do czynienia z tym problemem. Przed udostępnieniem mojego rozwiązania chcę podzielić się swoimi przemyśleniami.

Myślę, że „przycisk wyjścia” jest głupi. Naprawdę naprawdę bardzo głupio. I myślę, że użytkownicy (konsumenci), którzy proszą o przycisk wyjścia z twojej aplikacji, są również głupi. Nie rozumieją, jak działa system operacyjny i jak zarządza zasobami (i robi to świetną robotę).

Myślę, że jeśli napiszesz dobry kawałek kodu, który robi właściwe rzeczy (aktualizacje, zapisuje i wypycha) we właściwym momencie i warunkach oraz przy użyciu właściwych rzeczy (usługa i odbiornik) będzie działał całkiem dobrze i nikt nie będzie narzekał .

Aby to zrobić, musisz przestudiować i dowiedzieć się, jak działa system Android. W każdym razie jest to moje rozwiązanie, aby zapewnić użytkownikom „przycisk wyjścia”.

Utworzyłem menu opcji zawsze widoczne w każdej aktywności (mam super aktywność, która to robi).

Gdy użytkownik kliknie ten przycisk, dzieje się tak:

Intent intent = new Intent(this, DashBoardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

SharedPreferences settings = getSharedPreferences(getString(PREF_ID), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, true);

  // Commit the edits!
editor.commit();
startActivity(intent);
finish();

Zapisuję więc w SharedPreferences, że chcę zabić moją aplikację i zaczynam zamiar. Proszę spojrzeć na te flagi; te wyczyszczą wszystkie moje backstacki nazywając moją Aktywnością DashBoard, która jest moją aktywnością „domową”.

Tak więc w działaniu Dashboard uruchomiłem tę metodę w polu onResume:

private void checkIfForceKill() {

    // CHECK IF I NEED TO KILL THE APP

    // Restore preferences
    SharedPreferences settings = getSharedPreferences(
            getString(MXMSettingHolder.PREF_ID), Context.MODE_PRIVATE);
    boolean forceKill = settings.getBoolean(
            MusicSinglePaneActivity.FORCE_EXIT_APPLICATION, false);

    if (forceKill) {

        //CLEAR THE FORCE_EXIT SETTINGS
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean(FORCE_EXIT_APPLICATION, false);

        // Commit the edits!
        editor.commit();

        //HERE STOP ALL YOUR SERVICES
        finish();
    }
}

I będzie działać całkiem dobrze.

Jedyną rzeczą, której nie rozumiem, dlaczego tak się dzieje, jest to, że kiedy wykonuję ostatnie zakończenie (i sprawdziłem: śledzi cały prawidłowy przepływ onPause → onStop → onDestroy) aplikacja wciąż wykonuje ostatnią aktywność (ale jest puste).

Wygląda na to, że najnowsza intencja (która uruchomiła DashboardActivity) jest nadal w systemie.

Muszę kopać więcej, aby je również usunąć.


8
Niewielu konsumentów wie, czym jest system operacyjny, a tym bardziej jak działa, co nie czyni ich głupcami. Zażądanie przycisku Wyjdź / Wyjdź / Wyłącz sprawia, że ​​są normalne. Kiedy wychodzisz z pokoju, wyłączasz światła, a co ważniejsze, kiedy wychodzisz z domu, zamykasz drzwi i właśnie tutaj widzę problem z niemożnością poprawnego wyjścia z programu. Pozostawienie programu przy życiu w tle stanowi duże zagrożenie bezpieczeństwa.
Squiggles,

4
„Myślę, że„ przycisk wyjścia ”jest głupi”. Większość aplikacji udostępnia przycisk wyjścia.
IgorGanapolsky

Powiedziałeś „// TUTAJ ZATRZYMAJ WSZYSTKIE USŁUGI”, a następnie użyłeś metody finish (). Usługi Android nie mają metody finish (). Mają unbindService (mConnection);
IgorGanapolsky

@Squiggles Jeśli masz pokój, który automatycznie wyłącza wszystkie światła i zamyka drzwi po wyjściu, nie musisz się tym przejmować.
Seshu Vinay

7

Cykl życia aplikacji na Androida jest przeznaczony dla użytkowników telefonów komórkowych, a nie użytkowników komputerów.

Cykl życia aplikacji to brutalnie uproszczony paradygmat wymagany do przekształcenia serwera Linux w urządzenie konsumenckie.

Android to Java nad Linuksem, prawdziwy wieloplatformowy system operacyjny serwera. Tak rozprzestrzenił się tak szybko. Cykl życia aplikacji obejmuje rzeczywistą rzeczywistość systemu operacyjnego.

Dla użytkowników mobilnych aplikacje są właśnie zainstalowane lub nie. Nie ma koncepcji biegania ani wychodzenia. W rzeczywistości procesy aplikacji mają działać, dopóki system operacyjny nie zwolni ich ze względu na posiadane zasoby.

Ponieważ jest to przepełnienie stosu, każdy, kto to czyta, jest użytkownikiem komputera i musi wyłączyć 90% swojej wiedzy, aby zrozumieć cykl życia aplikacji mobilnej.


Nie podążam za twoim krokiem do „użytkownicy komputerów muszą wyłączyć 90% swojej wiedzy”. Tak, tak mówi Romain Guy, ale to nie prawda. Wydaje mi się, że sekcja „Zaawansowane opcje dla użytkowników komputerów” z przyciskiem „Wyjdź” zaspokoi potrzeby wszystkich.
Don Hatch,

Nie mam pojęcia, kim jest ten „Romain Guy” ani dlaczego mnie cytuje. Zamknięcie ostatnich zadań spowoduje zamknięcie aplikacji, podobnie jak zatrzymanie informacji o aplikacji. ADB umożliwia dostęp do powłoki dla zaawansowanych użytkowników.
Dominic Cerisano,

6

Przeczytanie tego pytania i odpowiedzi zajęło mi więcej czasu niż wdrożenie częściowo poprawnego cyklu życia aplikacji na Androida.

Jest to aplikacja GPS, która wyszukuje punkty i wysyła aktualną lokalizację do serwisu internetowego co kilka sekund za pomocą wątku ... To może być odpytywanie co 5 minut w przypadku Teda o aktualizację, a następnie onStop może po prostu rozpocząć aktualizację Ted był tak zadowolony martwisz się, czy ktoś został znaleziony (asynchroniczny Ted, nie koduj jak programista Windows, albo twoje programy będą działać jak programy Windows ... eww, to nie jest takie trudne).

Zrobiłem trochę kodu początkowego w onCreate, aby skonfigurować rzeczy na cały okres aktywności, w tym checkUpdate.start();:

...

@Override
public void onStart() {
    super.onStart();
    isRemote = true;
    checkUpdate.resume();

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
}

@Override
public void onPause() {
    isRemote = false;
    checkUpdate.suspend();
    locationManager.removeUpdates(luh);
    super.onStop();
}

Ten kod może być całkowicie niepoprawny, ale działa. To jedna z moich pierwszych aplikacji na Androida.

Voilà, aplikacja, która nie zużywa procesora, gdy jest w tle, ale jest natychmiast gotowa do ponownego otwarcia, ponieważ jest w pamięci RAM (chociaż nie trzyma pamięci RAM, jak w cyklu życia Androida) ... aplikacja jest zawsze gotowa, to telefon chłopaki / dziewczęta. Jeśli aplikacja ma zużywać całą pamięć RAM i nie może zostać zamknięta przez system operacyjny, może przestać dzwonić = P Dlatego system operacyjny musi mieć możliwość zamknięcia aplikacji, gdy jest w tle (jeśli aplikacja nie jest uruchomiona świnia zasobów nie zostanie zamknięta BTW), więc po prostu napiszmy lepsze aplikacje.


Nie powinieneś wywoływać metody super.onStop z metody onPause .. Wygląda na to, że to by wszystko popsuło.
Matt Wolfe

1
Po przeczytaniu około 20 filozoficznych odpowiedzi, które jedynie unikają pytania .... +1 za posiadanie jakiegoś kodu.
Pacerier

6

Za każdym razem, gdy przechodzisz do następnej strony przez zamiar, użyj:

`YourActivityname.this.finish()`;

Przykład:

Intent intent = new Intent(getApplicationContext(), SMS.class);

startActivity(intent);
MainActivity.this.finish();

Aby żadna aktywność nie była uruchomiona w tle, a gdy chcesz wyjść z aplikacji, użyj:

MainActivity.this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
getParent().finish();

To wyjście działało dla mnie jak urok :)


1
Nie wychodzi z aplikacji, tylko chodzi o Mainactivity.
Sharath,

1
Ale bądź ostrożny - onPause () NIE JEST wywoływany w przypadku killProcess i System.exit. Mieliśmy z tym pewne problemy.
Pavel Biryukov

4

W każdym razie, jeśli chcesz zakończyć aplikację, zawsze możesz zadzwonić System.exit(0);.


5
System.exit()NIE zabija Twojej aplikacji, jeśli masz więcej niż jedno działanie na stosie. Korzystający z niego programista Androida nie zrozumiał podstawowego cyklu życia aplikacji na Androida. Przeczytaj tę odpowiedź .
Dheeraj Vepakomma,

Pełne rozwiązanie z System.exit(0); stackoverflow.com/questions/2033914/…
Sohail Zahid

2
Właściwie System.exit () ma zabić swoją aplikację. Jeśli jednak funkcja System.exit () została wywołana z innego miejsca niż główna aktywność, Android zrestartuje aplikację z jedną aktywnością mniejszą na stosie. Wydaje mi się to niedorzeczną odpowiedzią na czysty, zamierzony System.exit. To znaczy, jeśli byłby to div0 lub jakaś niezamierzona awaria, być może byłoby grzeczne zrestartowanie. Ale te nawet nie powodują automatycznego ponownego uruchomienia, o ile pamiętam. Ale w każdym razie aplikacja zostaje zabita. Można go zrestartować, ale to nie znaczy, że nie został zabity.
Jesse Gordon,

3

Jeśli masz 10,20 .. uruchomionych wielu działań i chcesz je wszystkie zakończyć i wyjść z systemu.

Utwórz tablicę statyczną w application classlubconstants class.

Stałe

public class Constants {

public static ArrayList<Activity> activities = new ArrayList<Activity>();

}

MainActivity Dodaj bieżące odwołanie do aktywności w tej tablicy

activity = MainActivity.this; Constants.activities.add(activity);

public class MainActivity extends Activity {

    private ImageView imageButton;
    private Activity activity;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        activity = MainActivity.this;
        Constants.activities.add(activity);

        imageButton = (ImageView) findViewById(R.id.camera);
        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // existing app.
                if (Constants.activities != null) {
                    for (int i = 0; i < Constants.activities.size(); i++) {
                        Activity s = Constants.activities.get(i);
                        s.finish();
                    }
                }
                //super.finish();
                finish();
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
            }
        });
    }
}

1
Może to spowodować awarię aplikacji, gdy użytkownicy dwukrotnie klikną przycisk, zwłaszcza gdy system jest z jakiegokolwiek powodu obciążony. Można temu zapobiec, usuwając działania z tablicy.
Mam nadzieję, że będzie
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.