Видалення активності з стека історії


382

Мій додаток показує активність реєстрації, коли користувач запускає додаток, виглядає так:

  1. ActivitySplashScreen (ласкаво просимо в гру, підписуєтесь на рахунок?)
  2. ActivitySplashScreenSignUp (чудово, заповніть цю інформацію)
  3. ActivityGameMain (головний екран гри)

тому діяльність запускається одна з одною саме в тому порядку, коли користувач натискає кнопку на кожному екрані.

Коли користувач переходить від активності №2 до №3, чи можливо повністю стерти №1 та №2 зі списку історії? Мені б хотілося, щоб, якщо користувач перебуває під номером №3 і натискає кнопку назад, вони просто переходять на головний екран, а не назад на екран сплеску.

Я думаю, що я можу це виконати за допомогою завдань (наприклад, почати нове завдання на №3), але хотів дізнатися, чи існує простіший метод,

Дякую


Перебуваючи на головному екрані, коли користувач поновлює вашу програму, це перенесе його на ActivitySplashScreen або ActivityGameMain?
Таміл

Відповіді:


632

Ви можете досягти цього шляхом установки android:noHistory атрибута для "true"в відповідних <activity>записів у вашому AndroidManifest.xmlфайлі. Наприклад:

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

12
Це найкращий спосіб зробити це.
shkschneider

22
Еквівалентно можна використовувати FLAG_ACTIVITY_NO_HISTORY.
Тиммммм

34
Як я можу досягти цього з коду? Тому що я не хочу цього робити постійно. Я хотів би видалити дану діяльність з історії лише за деяких умов.
Намратха

8
Просто пам’ятайте, що використання атрибута noHistory дозволить завершити цю діяльність, що може спричинити несподівану поведінку, наприклад, з G + логіном. Дивіться: stackoverflow.com/questions/20383878/… Зайняв деякий час, щоб знайти цю помилку, оскільки мій додаток постійно виходив з ладу.
Акапулько

13
Копіювати потрібний прапор важко, оскільки це посилання, тому ось такий, який легко можна скопіювати. android:noHistory="true"
MirroredFate

137

Ви можете скористатися переадресацією, щоб видалити попередню активність із стеку дій під час запуску наступної. Приклад цього є в APIDemos , але в основному все, що ви робите, - це дзвонити finish()відразу після дзвінка startActivity().


1
Привіт, Даніеле, я читав приклад, але це очистить стек історії лише на 1 діяльність, чи не так? Якщо мій стек виглядає як A, B, і я запускаю C, я хочу, щоб C був новим коренем і повністю очистив A і B. У прикладі sdk виклик закінчення () від B залишив би мене стеком A , C, чи не так? Дякую.
Позначте

1
Ви можете очистити A під час запуску B і очистити B під час запуску C; однак, я думаю, тоді ви не змогли б відмовитися від B до A, якщо цього ви хочете. Мені доведеться подумати над цим, якщо це проблема.
Ден Лев

3
Позначте, щоб досягти того, що ви хочете, ви повинні використовувати прапор: FLAG_ACTIVITY_CLEAR_TOP. Я сподіваюся, що це допомагає.
Франсіско Юніор

3
FLAG_ACTIVITY_CLEAR_TOPне працюватиме, оскільки C ще не знаходиться в задній стеці.
Timmmm

1
@DanielLew У APIDemos так багато прикладів. У вас є назва запропонованого прикладу?
Стефан

52

Так, подивіться на Намір.FLAG_ACTIVITY_NO_HISTORY .


46
Зауважте, що це не встановлює історії для діяльності, яку ви запускаєте. Щоб у вас не було історії діяльності, яку ви починаєте, я просто встановив її android:noHistory="true"в маніфесті.
georgiecasey

1
Це добре працює. Використовуйте, intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)щоб встановити цей прапор.
vovahost

1
@georgiecasey це корисно, коли інколи хочеться зберегти його в історії, а часом не хочеться.
Віхаан Верма

24

Це, мабуть, не ідеальний спосіб зробити це. Якщо у когось є кращий спосіб, я буду з нетерпінням чекати його втілення. Ось як я виконав це конкретне завдання за допомогою попередньої версії 11 sdk.

у кожному класі, який ви хочете піти, коли настає ясний час, вам потрібно зробити це:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

тоді той, якому потрібно відкласти ланцюжок спливів зі стека, потрібно просто викликати це, коли ви хочете його ініціювати:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

Тоді заходи не на стеці!
Пам’ятайте, люди, що ви можете розпочати діяльність, а потім розпочати прибирання за нею.


Якщо хтось пізніше натрапить на це, я подумав, що може виявитися важливим знати, якщо ви повернули екран, андроїд допоможе перезапустити додаток для вас, коли ви виведете останню активність зі стека. Просто пам’ятайте про це!
Тревіс

Це хороша відповідь, якщо ви хочете лише видалити активність із стека на умовно, залежно від того, що робить користувач у наступній діяльності +1
theMothaShip

23

Один із способів, що працює до API 11, - це почати ActivityGameMainспочатку, а потім у onCreateцій діяльності розпочати свою ActivitySplashScreenдіяльність. ActivityGameMainЧи не буде з'являтися , як ви називаєте startActivity занадто рано для сплеску.

Тоді ви можете очистити стек при запуску ActivityGameMain, встановивши ці прапори на Намір:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

Ви також повинні додати це до ActivitySplashScreen:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

Тож натискання на цю діяльність не повернеться до вашої ActivityGameMain.

Я припускаю, що ви не хочете, щоб екран із сплеском не повернувся ні до того, щоб досягти цього, я пропоную встановити його noHistoryу своєму AndroidManifest.xml. Потім замість цього поставте goBackPressedкод у своєму ActivitySplashScreenSignUpкласі.

Однак я знайшов кілька способів, як це вирішити. Запустіть інший додаток із сповіщення, поки ActivitySplashScreenSignUpвідображається повідомлення, а історія повернення не скидається.

Єдиний реальний спосіб цього - в API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

20

Я використовую цей спосіб.

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

Дякую. Я вважаю це корисним у тому випадку, якщо в моєму меню була кнопка «Головна», і я не хотів, щоб з'явилася складова діяльність після того, як користувач натиснув звідти додому.
ghitesh

8

Я знаю, що я запізнююсь на це (минуло два роки з моменту запитання), але я досяг цього, перехопивши натиснувши кнопку назад. Замість того, щоб перевіряти конкретні дії, я просто розглядаю кількість, і якщо вона менше 3, вона просто надсилає додаток назад (призупиняючи програму та повертаючи користувача до того, що було запущено до запуску). Я перевіряю менше трьох, тому що у мене є лише один вступний екран. Також я перевіряю кількість, оскільки моя програма дозволяє користувачеві повертатися до головного екрана через меню, тому це дозволяє їм створювати резервні копії через інші екрани, як звичайні, якщо на стеку є інші дії, крім введення екрана.

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}

7

У маніфест можна додати:

android:noHistory="true"

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

Ви також можете зателефонувати

finish()

відразу після виклику startActivity (..)


2
Краще використовувати прапори діяльності, ніж ставити речі в маніфест.
Тревор Харт


4

Божевільно, що ніхто не згадав про це елегантне рішення. Це має бути прийнятою відповіддю.

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

Ключовим тут є використання intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); для посередника Activity. Після того, як середня ланка розірвана, DashActivityзаповіт буде першим і останнім у стеці.

android:noHistory="true"є поганим рішенням, оскільки воно спричиняє проблеми, коли покладається на Activityзворотний виклик, наприклад onActivityResult. Це рекомендоване рішення і його слід прийняти.


1
Цей прапор звучав занадто добре, щоб бути правдою. FLAG_ACTIVITY_NO_HISTORY працює чудово, і, як можна було б очікувати, поки хтось не поставить додаток на другий план, а потім знову на другий план, маючи активність із прапором у верхній частині стека. Переходячи на другий план, діяльність знищується. Повернувшись до програми, ви побачите попередню активність зі стека. Я точно не хотів такої поведінки.
NeverwinterMoon

4

Ще пізно, але сподіваюся, що це допомагає. Більшість відповідей не вказують у правильному напрямку. Для такої речі є два простих прапора.

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

З Документів Android:

загальнодоступний статичний кінцевий int FLAG_ACTIVITY_CLEAR_TASK Додано в рівні 11 API

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

діяльність, яку слід очистити до початку діяльності. Тобто активність стає новим коренем інакше порожнього завдання, і будь-які старі дії закінчуються. Це можна використовувати лише спільно з FLAG_ACTIVITY_NEW_TASK.


1

Просто зателефонуйте this.finish () перед запускомActivity (наміром) на зразок цього-

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

Користувачі, які мають помилку на "це", повинні змінити її на "ActivityOne.this"
ninbit

1

Видалення активності з історії відбувається, встановивши прапор перед тією діяльністю, яку ви не хочете

A-> B-> C-> D

Припустимо, A, B, C і D - це 4 дії, якщо потрібно очистити B і C, а потім встановити прапор

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

У діяльності А і В

Ось біт коду

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.