2010-08-25 10 views
9

Pracuję nad aplikacją z wieloma funkcjami. Chciałbym utworzyć trwałe powiadomienie, które (mniej więcej) mówi "AppName - Return to AppName", które będzie obecne przy każdym uruchomieniu usług w tle. Tworzenie i usuwanie powiadomienia nie było problemem.Użyj trwałego powiadomienia, aby umożliwić użytkownikowi powrót do działającej aplikacji na Androida.

Teraz użytkownik może znajdować się na jednym z kilku ekranów/działań, opuścić aplikację, a następnie ponownie wprowadzić aplikację za pośrednictwem powiadomienia. Problem to, zgłoszenie musi mieć intencję, która uruchamia określoną wcześniej aktywność z góry określoną aktywność. Chcę, aby powiadomienie ponownie wchodziło do aplikacji pod numerem , niezależnie od aktywności na szczycie stosu historii.

Pierwszą próbą obejścia tego brzydkiego rozwiązania było zrobienie działania (nazwijmy to "returnFromNotify"), którego jedynym zadaniem było "skończenie" się w "onCreate". Powiadomienie otworzy okno "returnFromNotify" w zakresie historii aplikacji, które następnie natychmiast się usunie, wysyłając użytkownika z powrotem do poprzedniego stanu historii w stosie aplikacji. To wydaje się działać ... chyba że użytkownik użył "wstecz", aby całkowicie wycofać się z aplikacji. Następnie, gdy trafią na powiadomienie, ładuje się "returnFromNotify", a następnie kończy, wysyłając je z powrotem na ekran główny (ponieważ w stosie historii nie ma żadnych aktywności dla aplikacji).

Zastanowiłem się, próbując wykryć, czy było coś w stosie historii przed "returnFromNotify", a jeśli nie, odpal moją główną aktywność. Nie mogę też znaleźć sposobu, żeby to zrobić.

Jakieś wejście lub sugestie nowicjusza Java/Android? FYI, Moja główna historia dotyczy języków opartych na skryptach.

Odpowiedz

6

Lubię swój oryginalny pomysł utworzenia „returnFromNotify” lepsze działanie niż proponowanego obejścia, gdyż jest możliwe do wykrycia, jeśli ResumeActivity jest na dnie stosu (a więc tylko aktywność w stosie) .

Oto w jaki sposób można to zrobić:

Dodaj ResumeActivity do manifestu i określić atrybut noHistory:

<activity android:name=".ResumeActivity" android:noHistory="true" /> 

Określanie Nohistory będzie upewnić się, działalność ta nie pozostanie w stosie najszybciej jak się kończy. W ten sposób wiesz, że tylko aktualnie działająca instancja ResumeActivity pojawi się w stosie.

W celu sprawdzenia stos aplikacji, będziesz też musiał prosić o pozwolenie GET_TASKS:

<uses-permission android:name="android.permission.GET_TASKS" /> 

Teraz można użyć ActivityManager::getRunningTasks() celu ustalenia, czy ResumeActivity jest tylko aktywność w stosie:

public class ResumeActivity extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     if(isOnlyActivityInStack()) { //check the application stack 
      //This activity is the only activity in the application stack, so we need to launch the main activity 
      Intent main = new Intent(this, MainActivity.class); 
      main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
      startActivity(main); 
     } else { 
      //Return the user to the last activity they had open 
      this.finish(); 
     } 
    } 

    /** 
    * Checks the currently running tasks. If this activity is the base activity, we know it's the only activity in the stack 
    * 
    * @return boolean This activity is the only activity in the stack? 
    **/ 
    private boolean isOnlyActivityInStack() { 
     ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
     boolean onlyActivityInStack = false; 

     for(RunningTaskInfo tasks : manager.getRunningTasks(Integer.MAX_VALUE)) { 
      if(tasks.baseActivity.getPackageName().equals(this.getPackageName())) { //find this package's application stack 
       if(tasks.baseActivity.getClassName().equals(this.getClass().getName())) { 
        //If the ResumeActivity is the base activity, we know that it is the only activity in the stack 
        onlyActivityInStack = true; 
        break; 
       } 
      } 
     } 

     return onlyActivityInStack; 
    } 

} 

Wiem, że zadałeś to pytanie ponad 2 lata temu, ale udzielam tej odpowiedzi na wypadek, gdyby ktoś inny wpadł w tę konkretną sytuację (tak jak ja). Myślę, że byłeś na dobrej drodze dzięki rozwiązaniu, do którego pierwotnie dążyłeś.

+0

Tak! Ten projekt był dla pracy, z którą już nie jestem, więc zupełnie jej nie potrzebuję ... ale brzmi to tak DOKŁADNIE, czego szukałem, więc dziękuję! Mam nadzieję, że ktoś inny również uzna to za przydatne. – Slobaum

3

OK, wierzę, że znalazłem satysfakcjonującą pracę - około dla mojego konkretnego przypadku. Dodałem statyczną liczbę całkowitą do mojej "mainActivity", a za każdym razem, gdy jest uruchamiane "onCreate", zwiększa ona liczbę całkowitą. Za każdym razem, gdy jest uruchamiane "onDestroy", zmniejsza się.

W moim "returnFromNotify", patrzę na statyczną liczbę całkowitą, aby zobaczyć, czy jest większa niż 0. Jeśli tak, zakładam, że jest aktywna "mainActivity", i że uruchomione "zakończ" wewnątrz "returnFromNotify" zwróci tam. W przeciwnym razie zakłada, że ​​użytkownicy "wycofali się", skończą, a następnie używają "startActivity" do odpalenia nowej instancji "mainActivity".

To nie jest uniwersalne rozwiązanie, ale moim zdaniem wystarczy. Wciąż jestem otwarty na inne odpowiedzi, a jeśli ktoś może przebić dziurę w mojej logice, zrób to - konstruktywna krytyka jest mile widziana. Dzięki.

1

Chyba nie ma łatwego sposobu, aby to zrobić, ale zamiast dodawać licznik w główną działalność chciałbym przedłużyć Application:

klasa bazowa dla tych, którzy muszą utrzymać globalny stan aplikacji. Można dostarczyć własnej implementacji przez podając jej nazwę w swojej AndroidManifest.xml za tag, który spowoduje, że klasa będzie instancja dla ciebie, gdy proces dla aplikacji/pakietu jest utworzony.

bym mantein logiki tam i metody takie jak:

public Intent getIntentForLastActivityShown(); 

nazywać, gdy pozycja powiadomienie kliknięciu.

+1

Jak można użyć funkcji getIntentForLastActivityShown()? Nie byłoby prostszym sposobem, aby zachować uchwyt powiadomienia w klasie Application, a następnie za każdym razem, gdy rozpoczyna się nowe zestawienie intencji setLatestEventInfo z notyfikacji i zaktualizować oczekującyIntent do bieżącego widocznego działania. – schwiz

1

Moim pierwszym podejściem byłoby użycie SharedPreferences i przechowywanie pary wartości kluczy o nazwie podobnej do lastDisplayedActivity. Następnie w każdej aktywności na onResume (i ewentualnie `onCreate ') byś mieć linię:

sharedPreferences.edit().putInteger("lastDisplayedActivity", ReturnFromNotify.THIS_ACTIVITY_NAME); 

Innymi słowy, można przechowywać zmiennej szerokości aplikacji wskazujący których aktywność ostatnio wyświetlany. Następnie wystarczy pobrać tę zmienną z SharedPreferences i uruchomić odpowiednie działanie.

+0

To nie jest zły pomysł, ale wymagałoby to dodania kodu do cyklu życia każdego działania (którego wolałbym nie robić). Czy uruchomienie odpowiedniej aktywności zachowałoby stan poprzedniej instancji działania, czy też spowodowałoby to nowe wystąpienie tego działania? Naprawdę potrzebuję tego, aby zachować jakikolwiek stan, w którym się znajdowali. – Slobaum

+0

Może on automatycznie przywrócić stan, ale jeśli twoja aktywność nie jest aktualnie wyświetlana, Android * może ją zabić w dowolnym momencie *, aby odzyskać dodatkową pamięć. Innymi słowy, jeśli chcesz mieć pewność, że zapiszesz stan działania, musisz go przechowywać w innym miejscu. Istnieje wiele sposobów, aby to zrobić, ale jeśli masz sporą ilość danych, polecam korzystanie z bazy danych SQLite: http://developer.android.com/guide/topics/data/data-storage.html#db – Computerish

0

Zwykle używam aktywności o nazwie "Launcher", która sprawdza stan mojego wniosku model i rozpoczyna działania (lub robi inne rzeczy) w zależności od zasad modelu. Wstawiłem obiekt Model w mojej klasie aplikacji. Model można użyć Preferencje do przechowywania jego stanu. Robię to, aby uniknąć pól statycznych w działaniach.

Powiązane problemy