Закройте приложение и запустите домашний экран на Android

У меня есть два разных вида деятельности. Первый запускает второй. Во втором упражнении я звоню System.exit(0) чтобы принудительно закрыть приложение, но автоматически отображается первое действие вместо возврата приложения на начальный экран. Как я могу избежать этого и заставить приложение вернуться на домашний экран?

21 ответ

Решение

Вы должны действительно думать о том, чтобы не выходить из приложения. Это не то, как обычно работают приложения для Android.

Краткий ответ: звонок moveTaskToBack(true) на вашеActivity вместо System.exit(), Это будет скрывать ваше приложение, пока пользователь не захочет использовать его снова.

Более длинный ответ начинается с другого вопроса: почему вы хотите убить ваше приложение?

ОС Android управляет управлением памятью и процессами, и так далее, поэтому мой совет - пусть Android позаботится об этом за вас. Если пользователь хочет покинуть ваше приложение, он может нажать кнопку "Домой", и ваше приложение фактически исчезнет. Если телефону потребуется больше памяти, операционная система прекратит работу вашего приложения.

Если вы правильно реагируете на события жизненного цикла, ни вам, ни пользователю не нужно заботиться о том, работает ли ваше приложение или нет.

Так что если вы хотите скрыть вызов приложения moveTaskToBack() и пусть Android решит, когда его убить.

Самый простой способ для достижения этой цели приведен ниже (без влияния на собственное управление памятью в Android. Нет необходимости в уничтожении процессов).

  1. Запустите действие, используя это намерение:

    Intent intent = new Intent(this, FinActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    finish();
    
  2. В целевой деятельности FinActivity.classвызовите финиш () в onCreate,

Объясненные шаги:

  1. Вы создаете намерение, которое стирает все другие действия (FLAG_ACTIVITY_CLEAR_TOP) и удалите текущую активность.

  2. Деятельность разрушает себя. Альтернативой является то, что вы можете сделать заставку в FinActivity. Это необязательно.

Android имеет механизм для безопасного закрытия приложения в соответствии с его документацией. В последнем действии, которое было завершено (обычно это основное действие, которое впервые возникло при запуске приложения), просто поместите пару строк в метод onDestroy(). Вызов System.runFinalizersOnExit(true) гарантирует, что все объекты будут завершены и сборщик мусора при выходе из приложения. Например:

public void onDestroy() {
    super.onDestroy();

    /*
     * Notify the system to finalize and collect all objects of the
     * application on exit so that the process running the application can
     * be killed by the system without causing issues. NOTE: If this is set
     * to true then the process will not be killed until all of its threads
     * have closed.
     */
    System.runFinalizersOnExit(true);

    /*
     * Force the system to close the application down completely instead of
     * retaining it in the background. The process that runs the application
     * will be killed. The application will be completely created as a new
     * application in a new process if the user starts the application
     * again.
     */
    System.exit(0);
}

Наконец, Android не будет уведомлять приложение о событии клавиши HOME, поэтому вы не можете закрыть приложение, когда нажата клавиша HOME. Android резервирует ключевое событие HOME для себя, чтобы разработчик не мог запретить пользователям выходить из приложения.

Вы также можете указать noHistory = "true" в теге для первого действия или завершить первое действие, как только начнете второе (как сказал Дэвид).

AFAIK, "принудительное закрытие" убивает процесс, в котором размещается JVM, в которой выполняется ваше приложение, а System.exit() завершает JVM, на которой выполняется экземпляр вашего приложения. Оба являются формой резких завершений и не рекомендуется для нормального потока приложений.

Так же, как перехват исключений для охвата логических потоков, которые может выполнять программа, не рекомендуется.

Когда вы запускаете второе действие, finish() первый сразу:

startActivity(new Intent(...));
finish();

Я использую этот метод, чтобы закрыть деятельность!

public static void closeAllBelowActivities(Activity current) {
    boolean flag = true;
    Activity below = current.getParent();
    if (below == null)
        return;
    System.out.println("Below Parent: " + below.getClass());
    while (flag) {
        Activity temp = below;
        try {
            below = temp.getParent();
            temp.finish();
        } catch (Exception e) {
            flag = false;
        }
    }
}

android.os.Process.killProcess(android.os.Process.myPid()); работает нормально, но рекомендуется позволить платформе Android беспокоиться об управлении памятью:-)

Я использую это:

1) Родительское действие вызывает вторичное действие с методом "startActivityForResult"

2) Во вторичной деятельности при закрытии:

int exitCode = 1; // Select the number you want
setResult(exitCode);
finish();

3) И в родительской активности переопределите метод "onActivityResult":

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    int exitCode = 1;
    if(resultCode == exitCode) {
        super.setResult(exitCode); // use this if you have more than 2 activities
        finish();
    }
}

Это прекрасно работает для меня.

Использовать finish метод. Это более простой и легкий способ.

this.finish();

Вы не можете сделать System.exit(), это не безопасно.

Вы можете сделать это: Process.killProcess(Process.myPid());

Вы неправы. Есть один способ убить приложение. В классе с суперклассом Application мы используем какое-то поле, например, killApp, Когда мы запускаем заставку (первое действие) в onResume()мы устанавливаем параметр для false для поля killApp, В каждой деятельности, которую мы имеем, когда onResume() в конце называется, мы называем что-то вроде этого:

if(AppClass.killApp())
    finish();

Каждое действие, попадающее на экран, должно вызывать onResume(), Когда он вызывается, мы должны проверить, если наше поле killApp правда. Если это правда, текущие действия называют finish(), Чтобы вызвать полное действие, мы используем следующую конструкцию. Например, в действии для кнопки:

AppClass.setkillApplication(true);
   finish();
   return;

Попробуйте следующее. Меня устраивает.

ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1); 
ComponentName componentInfo = taskInfo.get(0).topActivity;
am.restartPackage(componentInfo.getPackageName());

Имейте в виду, что при работе с приложениями, использующими постоянные сокетные соединения, finish() Метод не освобождает соединение. При нормальных обстоятельствах, finish() это лучший вариант, но если вам абсолютно необходимо выйти из приложения и освободить все ресурсы, которые он использует, используйте killProcess, У меня не было проблем с его использованием.

Скажем, у вас есть стек активности, такой как A>B>C>D>E. Вы находитесь на занятии D и хотите закрыть свое приложение. Это то, что вы будете делать -

В Деятельности, с которой вы хотите закрыть (Активность D)-

Intent intent = new Intent(D.this,A.class);
intent.putExtra("exit", "exit");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

В вашей RootActivity (то есть вашей основной активности, здесь Activity A) -

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent.hasExtra("exit")) {
            setIntent(intent);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (getIntent() != null) {
            if (("exit").equalsIgnoreCase(getIntent().getStringExtra(("exit")))) {
                onBackPressed();
            }
        }
    }

onNewIntent используется, потому что если активность активна, она получит первое намерение, которое ее начало. Не новый. Для более подробной информации - Документация

Запустите второе действие с startActivityForResult, а во втором возвращайте значение, которое один раз в методе onActivityResult первого действия закрывает основное приложение. Я думаю, что это правильный способ, которым Android делает это.

Это на самом деле тихо легко.

Я делаю это, сохраняя флаг в статической переменной, доступной для всех. Затем, когда я выхожу, я устанавливаю этот флаг, и все мои действия проверяют этот флаг onResume, Если флаг установлен, я выдаю System.exit на этой деятельности.

Таким образом, все действия будут проверяться на наличие флага и будут корректно закрываться, если флаг установлен.

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

В базовой активности onCreate и onResume после вызова супер-вызовов я проверяю этот флаг. Если "applicationShutDown" имеет значение true, я вызываю финиш для текущей операции.

Это сработало для меня:

protected void onResume() {
    super.onResume();
    if(BaseActivity.shutDownApp)
    {
        finish();
        return;

    }}

Я решил похожую проблему: MainActivity запускает BrowserActivity, и мне нужно закрыть приложение, когда пользователь нажимает Назад в BrowserActivity - чтобы не возвращаться в MainActivity. Итак, в MainActivity:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "sm500_Rmt.MainActivity";
    private boolean m_IsBrowserStarted = false;

а затем в OnResume:

    @Override
protected void onResume() {
    super.onResume();
    if(m_IsBrowserStarted) {
        Log.w(TAG, "onResume, but it's return from browser, just exit!");
        finish();
        return;
    }
    Log.w(TAG, "onResume");

... затем продолжайте OnResume. И, когда запустить BrowserActivity:

    Intent intent = new Intent(this, BrowserActivity.class);
    intent.putExtra(getString(R.string.IPAddr), ip);
    startActivity(intent);
    m_IsBrowserStarted = true;

И, похоже, работает хорошо!:-)

Запустите второе действие, используя начальное действие для результата:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);

//This line is important
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

startActivityForResult(intent, REQUEST_CODE);

Добавьте эту функцию к первому действию:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(rquestCode == REQUEST_CODE)
        if(resultCode == RESULT_CANCELED)
            finish();
}

И добавьте это ко второму занятию:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {

        Log.i(TAG, "Back key pressed");
        setResult(RESULT_CANCELED);
        finish();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

Это не рекомендуется, но вы все еще можете использовать это. Лучше использовать это решение, если вам нужно выйти из приложения.

По моему мнению, лучшее решение - завершить все действия в вашем приложении, как показано ниже.

Шаг 1. Поддержание статической переменной в mainacctivity. Сказать,

public static boolean isQuit = false;

Шаг 2. При событии нажатия кнопки установите для этой переменной значение true.

mainactivity.isQuit = true;
finish();

Шаг 3. И в каждом действии вашего приложения, есть onrestart метод, как показано ниже.

@Override
protected void onRestart() {
    // TODO Auto-generated method stub
    super.onRestart();
    if(mainactivity.isQuit)
        finish();
}
Другие вопросы по тегам