Як перевірити, чи активність є останньою у стеці активності для програми?


122

Я хочу знати, чи повернеться він на головний екран, якщо він вийде з поточної активності.



43
Щойно з’ясував, що в діяльності, яка називається isTaskRoot , є функція, яка, напевно, може вам допомогти.
H9kDroid

Відповіді:


116

ОНОВЛЕННЯ (липень 2015 р.):

Оскільки getRunningTasks () отримати НЕ рекомендується, від API 21, краще слідувати raukodraug відповідь або Ед Бернетт один (я б віддав перевагу другому).


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

Отже, щоб визначити, чи є діяльність останньою:

  • запит дозволів android.permission.GET_TASKS у маніфесті.
  • Використовуйте наступний код:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }

Зверніть увагу, що зазначений вище код буде дійсним лише у випадку, якщо у вас є одне завдання. Якщо існує можливість, що для вашої програми буде кількість завдань - Вам потрібно буде перевірити інші елементи списку завдань . Детальніше про завдання Завдання та зворотний стек



25
H9kDroid зробив правильну пропозицію. Вибрана відповідь - хак. Слід зробити це правильно, використовуючи isTaskRoot()метод.
Суфіан

@Sufian, де це особливо зламати? Код є логічним і використовує відкриті андроїд-API таким чином, яким вони мали намір використовуватись (наприклад, getRunningTasks слід використовувати для запуску завдань, і можна було б викликати його лише з метою аналізу цих завдань). Використання get (0) добре задокументовано та логічно: "Поверніть список завдань, які зараз виконуються. Найновіші - перші та старіші після того".
sandrstar

2
getRunningTasks () застаріло в рівні API 21
gilchris

Чи можу я зробити те ж саме для фрагментів. Якщо так, то як? Будь ласка, допоможіть
Sagar Devanga

1
@ Mr.Drew побачила найвищу відповідь від @ raukodraug
David Wasser

167

Я збираюся розмістити коментар @ H9kDroid як найкращу відповідь тут для людей, які мають подібне питання.

Ви можете використовувати isTaskRoot (), щоб знати, чи є дія кореня завдання.

Я сподіваюся, що це допомагає


1
Ви можете, будь ласка, надати єдиний рядок коду, щоб було зрозуміло, як користуватися isTaskRoot. Дякую.
Kaveesh Kanwal

18
@TheHunterif (isTaskRoot()) { // do something }
howettl

3
Єдина проблема полягає в тому, що на <= 4.4 я бачу, як вона робить іншу поведінку, ніж у> = 5.x. Здається, завжди повертається помилковим.
кругляки

Я думаю, вам слід розглянути можливість включення у відповідь зразкового коду, наданого в коментарях, щоб полегшити майбутнім читачам.
Ісак

відмінна відповідь. у моєму випадку після натискання користувачем сповіщення активність може стати коренем, якщо він закрив програму раніше
dave o grady

19

Сподіваюсь, це допоможе новачкові. На підставі вищевідповідей, які добре працюють для мене, я також ділю фрагмент коду, тому це буде легко реалізувати.

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

У вашій діяльності

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }


5

Хоча може бути спосіб досягти цього (див. Інші відповіді), я б запропонував вам цього не робити. Звичайним програмам Android не слід знати, чи збирається відобразити головний екран чи ні.

Якщо ви намагаєтеся зберегти дані, введіть код збереження даних у свій метод onPause (). Якщо ви намагаєтесь дати можливість користувачеві змінити свою думку щодо наявної програми, ви можете перехопити клавішу "Вгору / Вниз" для клавіші "Назад" та метод "onBackPress ()" та подати їм "Ви впевнені?" підказка.


1
Як щодо того, якщо мені потрібна послуга, запущена до тих пір, поки користувач не припинив свою діяльність? Я не можу захопити жодну функцію, як onStop, тому що їх можна викликати після вимкнення екрана.
Майкл

2
Якщо фонова служба запускає Діяльність, можливо, ви хочете дізнатися, чи є це єдиною діяльністю у стеку.
Метт W

4

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

Щоразу, коли ви починаєте нову діяльність, вставляйте маркер:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

Ви можете перевірити це так:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")

1
Не працює, якщо активність загине, і стек активності реконструюється - кожна діяльність на вимогу.
AlikElzin-kilaka

3

Проблема з використанням рішення sandrstar полягає в ActivityManagerтому, що вам потрібен дозвіл, щоб отримати завдання таким чином. Я знайшов кращий спосіб:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

У Activityнижній частині стека завжди ця категорія повинна бути за замовчуванням, тоді як інші види діяльності не повинні її отримувати.
Але навіть якщо це не вдається на деяких пристроях, ви можете встановити його під час запуску Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);

Що робити, якщо активність буде відкрита з push-повідомлення? У них немає CATEGORY
LAUNCHER

Я впевнений, що друга частина моєї відповіді все ще стосується. Ви можете встановити категорію як підказку у намірі. У цьому випадку, можливо, в контексті вашого повідомлення. Крім цього, ви також можете використовувати для цього прапори. бачити це посилання для створення повідомлень з умислом: stackoverflow.com/questions/13716723 / ...
А. Binzxxxxxx

Але якщо ваша найдавніша діяльність - це MainActivity, і тепер її відновлено, а потім ви отримаєте сповіщення про натиск і встановите очікуваний намір відкрити за допомогою CATEGORY_LAUNCHER, тоді у вас буде дві дії з цією категорією. Можливо, на різні завдання, хоча
nbtk

Я не зовсім впевнений, як це працює з повідомленнями. Я ніколи не використовував їх, як ти це робиш тут. Я впевнений, що існує такий простий спосіб зробити цей підхід, але я не торкався андроїд-коду з першого кварталу 2014 року. Можливо, ви хочете використовувати для цієї справи другу категорію? Або якийсь прапор? Але я здогадуюсь, що його склад працює так. Як щодо запуску основної діяльності та додавання якоїсь метаінформації, щоб потім відкрити правильну діяльність?
A. Binzxxxxxx

2

Я створив базовий клас для всіх своїх заходів, розширивши AppCompatActivity , і який має статичний лічильник:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

Це поки що спрацювало досить добре; і незалежно від версії API. Звичайно, потрібно, щоб усі види діяльності поширювали цей базовий клас - чим вони займаються, в моєму випадку.

Редагувати: я помітив один екземпляр, коли лічильник опускається до нуля до того, як програма повністю вийде, це коли зміна орієнтації та відкрита лише одна активність. Коли орієнтація змінюється, активність закривається і створюється інша, так onDestroyedназивається остання активність, а потім onCreateвикликається, коли створюється однакова діяльність зі зміненою орієнтацією. Цю поведінку необхідно враховувати; ОрієнтаціяEventListener може бути використана.


0

Android реалізує стек "Діяльність", пропоную прочитати про це тут . Схоже , все , що ви хочете зробити , хоча це отримати викликає активність: getCallingActivity(). Якщо поточна активність - це перша активність у вашій програмі, а програма запущена з головного екрану, вона повинна (я припускаю) повернутися null.


9
Це не буде працювати, оскільки getCallingActivity () поверне нульове значення, якщо діяльність не була запущена через startActivityForResult ().
H9kDroid

0

Одне, що тут пропустили, - це натискання клавіші «Домашня клавіша», коли активовано, ви не можете виявити це у своїй діяльності, тому краще керувати стеком активності програмно керуючи натисканням кнопки «Назад» та переходом до потрібної діяльності або просто роблячи необхідні кроки.

Крім того, ви не можете бути впевнені, що починаючи свою діяльність зі списку "Недавня активність", можна виявити, встановивши додаткові дані в намірі відкрити активність, оскільки вони повторно використовуються в цьому випадку.

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