Как исправить приложение перейти в фоновый режим после переупорядочения вперед и назад

В настоящее время мне удалось разрешить пользователю переключаться между двумя различными группами действий (скажем, 4 класса активности A/B группа и группа X/Y) и переключаться с помощью FLAG_ACTIVITY_REORDER_TO_FRONT флаг, но я заметил странное поведение:

A ->(start activity)  X
X ->(reorder to front) A 
X , A ->(start) B ->(start) B2
A , B , B2 ->(reorder to front) X ->(start) Y
X , Y ->(reorder to front) A , B , B2 
X , Y , A , B <-(press back, app hide to background, B2 destroyed)  B2 
X , Y , A , B (click to foreground, B is here just fine)

Как предотвратить скрытие приложения в фоновом режиме B2?

Я заметил, что это происходит только в одном классе (B а также B2 это тот же класс), если я использую B а также C, это не будет такой проблемой, я хотел бы знать, в чем причина.

А также X ->(start) Y также ключ к его воспроизведению.

Я пытался использовать пользовательский список экземпляров уровня приложения для обнаружения B2"s onPause() а также isFinishing() а также startActivty() B, но он всегда звонит B"s onCreate() хотя с использованием FLAG_ACTIVITY_REORDER_TO_FRONTчто заставляет меня думать, что это не правильное решение. Правильное решение должно выяснить, как предотвратить скрытие приложения в фоновом режиме.

1 ответ

Решение

Я неправильно понимаю FLAG_ACTIVITY_REORDER_TO_FRONT флаг. Я думал, что деятельность Y FLAG_ACTIVITY_REORDER_TO_FRONT активность C сохранит родителя, поэтому C backpress перейдет к B. Нет, это не так. FLAG_ACTIVITY_REORDER_TO_FRONT фактически делает передачу C новому родителю Y (то есть вызывающему), но так как родитель Y находится над C, то обратное нажатие C не сможет перейти в Y и сворачиваться / скрываться от фона.

Я также неправильно понимаю мой код создания 2 стека, но на самом деле это всего лишь один стек. Я должен использовать FLAG_ACTIVITY_MULTIPLE_TASK чтобы сделать это несколько стеков.

Мне также нужно определить правильный launchMode в декларации:

  • Обе активности запуска A и X должны быть определены как singleInstance в манифесте.
  • Обе операции домашней страницы B и Y должны быть определены как singleTopв манифесте.
  • Другие действия C и Z ... и т. Д. Должны быть определены какsingleTask в манифесте.

Деятельность A должна установить флаг Intent.FLAG_ACTIVITY_MULTIPLE_TASK когда начать домашнюю страницу B. X также должен установить флаг Intent.FLAG_ACTIVITY_MULTIPLE_TASK когда стартует домашняя страница Y.

Если задача вкладки уже была запущена ранее, допустимыми флагами для циклического переупорядочения всех одинаковых действий задачи (сохранения в глобальном списке стека) являютсяmoveTaskToBack(true); одиночная строка также работает, но она не может вернуться на передний план):

intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
                            |Intent.FLAG_ACTIVITY_NEW_TASK
                            |Intent.FLAG_ACTIVITY_NO_ANIMATION); 

p / s: вышеописанное не будет работать в Android 5 и 6, которые будут переупорядочивать только одну верхнюю активность, поэтому мне нужно добавить android.permission.REORDER_TASKS в манифесте и сделайте это (подробнее, см. отчет об ошибке):

ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (final Activity a : YStackClasses) {
    if (IsBeforeAndroidNougat && (tasksManager != null)) {
        tasksManager.moveTaskToFront(a.getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION); 
    } else { 
        //Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
    }
}

Если задача вкладки никогда не запускалась, следует запустить активность запуска без установки какого-либо специального флага.

Для предотвращения нажатия кнопки запуска обновится из-за singleInstanceЯ также должен сделать проверку в A и B, поставить его перед setContentView а также finish()/return; рано.

if (getIntent() != null && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
    && getIntent().getAction() != null
    && getIntent().getAction().equals(Intent.ACTION_MAIN)) {
    //figure out latest activity and it's home activity, and reorder to front, and its entire task stack will focus on top.
}

Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK больше не будет автоматически очищать все действия, чтобы обновить приложение, решение ActivityCompat.finishAffinity(desiredTask's Top Act);, который удалит все активы из верхней части активности, не влияя на стек других задач.

Если класс повторного использования, например, C1, C2, то я должен использовать startActivityForResult(intent, dummyResponse); заставить его создать новую деятельность на вершине того же класса. Но не делайте этого, когда А начинает деятельность с startActivityForResult требует одной задачи и игнорировать singleInstance launchMode, смотрите эту ветку. И не делай ForResult внутри onNewIntent() что может привести к тому, что страница будет сгенерирована дважды в стеке (вторая страница генерируется не сразу, а только после возвращения). Но я могу сделать ForResult в вызывающей onNewIntent() вступить в силу.

Мне также нужно сделать это, чтобы заставить работать спину должным образом в домашних условиях, чтобы скрыть приложение и вернуться на нужную страницу задач. Я не пользуюсь TASK_ON_HOME(при запуске домашней страницы B класса) помечают, потому что это только одно направление задачи (т. е. приоритет перед фиксированной активностью, а не зависит от предыдущей главной задачи):

@Override //B class
public void onBackPressed() {
    moveTaskToBack(true); //B task stack
    if (YStackClasses.size() > 0) { //Y task stack
        try {
            YStackClasses.get(0).moveTaskToBack(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    super.onBackPressed();
}

И будьте осторожны, стек приложений может кешироваться, даже несмотря на то, что он перезапускается автоматически из-за сбоя, поэтому иногда вам нужно выполнить повторный запуск дважды, чтобы вернуться в исходное состояние стека для тестирования, иначе вы получите неправильный вывод.

Вот и все, в этом ответе может не быть подробностей кода, но он должен помочь, если вы столкнетесь с такой же проблемой "скрыть фон при повторном нажатии", как я, вы можете понять, насколько сложно добиться ожидаемого поведения, если вы установили неправильный флаг за один шаг или определен неправильно launchMode в одном из действий в манифесте.

Другие вопросы по тегам