Как закрыть приложение Android? - PullRequest
156 голосов
/ 19 января 2010

Я хочу закрыть свое приложение, чтобы оно больше не работало в фоновом режиме.

Как это сделать?Это хорошая практика на платформе Android?

Если я полагаюсь на кнопку «назад», приложение закрывается, но остается в фоновом режиме.Есть даже приложение под названием «TaskKiller», просто чтобы убить эти приложения в фоновом режиме.

Ответы [ 21 ]

139 голосов
/ 18 февраля 2011

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

Также Android не будет уведомлять приложение о событии ключа HOME , поэтому вы не можете закрытьприложение при нажатии клавиши HOME .Android резервирует ключевое событие HOME для себя, чтобы разработчик не мог запретить пользователям выходить из приложения.Однако вы можете определить с помощью клавиши HOME , установив флаг в значение true в классе помощника, который предполагает, что была нажата клавиша HOME , и затем изменить флаг на false, когдапроисходит событие, которое показывает, что клавиша HOME не была нажата, а затем проверяется, чтобы увидеть нажатие клавиши HOME в методе действия onStop () .

Не забывайте обращаться с клавишей HOME для любых меню и действий, запускаемых этими меню.То же самое касается клавиши SEARCH .Ниже приведены примеры классов для иллюстрации:

Вот пример корневого действия, которое убивает приложение, когда оно уничтожено:

package android.example;

/**
 * @author Danny Remington - MacroSolve
 */

public class HomeKey extends CustomActivity {

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

        /*
         * Kill application when the root activity is killed.
         */
        UIHelper.killApp(true);
    }

}

Вот абстрактное действие, которое может быть расширено для обработки HOME для всех действий, которые его расширяют:

package android.example;

/**
 * @author Danny Remington - MacroSolve
 */

import android.app.Activity;
import android.view.Menu;
import android.view.MenuInflater;

/**
 * Activity that includes custom behavior shared across the application. For
 * example, bringing up a menu with the settings icon when the menu button is
 * pressed by the user and then starting the settings activity when the user
 * clicks on the settings icon.
 */
public abstract class CustomActivity extends Activity {
    public void onStart() {
        super.onStart();

        /*
         * Check if the app was just launched. If the app was just launched then
         * assume that the HOME key will be pressed next unless a navigation
         * event by the user or the app occurs. Otherwise the user or the app
         * navigated to this activity so the HOME key was not pressed.
         */

        UIHelper.checkJustLaunced();
    }

    public void finish() {
        /*
         * This can only invoked by the user or the app finishing the activity
         * by navigating from the activity so the HOME key was not pressed.
         */
        UIHelper.homeKeyPressed = false;
        super.finish();
    }

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

        /*
         * Check if the HOME key was pressed. If the HOME key was pressed then
         * the app will be killed. Otherwise the user or the app is navigating
         * away from this activity so assume that the HOME key will be pressed
         * next unless a navigation event by the user or the app occurs.
         */
        UIHelper.checkHomeKeyPressed(true);
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.settings_menu, menu);

        /*
         * Assume that the HOME key will be pressed next unless a navigation
         * event by the user or the app occurs.
         */
        UIHelper.homeKeyPressed = true;

        return true;
    }

    public boolean onSearchRequested() {
        /*
         * Disable the SEARCH key.
         */
        return false;
    }
}

Вот пример экрана меню, который обрабатывает клавишу HOME :

/**
 * @author Danny Remington - MacroSolve
 */

package android.example;

import android.os.Bundle;
import android.preference.PreferenceActivity;

/**
 * PreferenceActivity for the settings screen.
 * 
 * @see PreferenceActivity
 * 
 */
public class SettingsScreen extends PreferenceActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.layout.settings_screen);
    }

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

        /*
         * This can only invoked by the user or the app starting the activity by
         * navigating to the activity so the HOME key was not pressed.
         */
        UIHelper.homeKeyPressed = false;
    }

    public void finish() {
        /*
         * This can only invoked by the user or the app finishing the activity
         * by navigating from the activity so the HOME key was not pressed.
         */
        UIHelper.homeKeyPressed = false;
        super.finish();
    }

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

        /*
         * Check if the HOME key was pressed. If the HOME key was pressed then
         * the app will be killed either safely or quickly. Otherwise the user
         * or the app is navigating away from the activity so assume that the
         * HOME key will be pressed next unless a navigation event by the user
         * or the app occurs.
         */
        UIHelper.checkHomeKeyPressed(true);
    }

    public boolean onSearchRequested() {
        /*
         * Disable the SEARCH key.
         */
        return false;
    }

}

Вот пример вспомогательного класса, который обрабатывает клавишу HOME в приложении:

package android.example;

/**
 * @author Danny Remington - MacroSolve
 *
 */

/**
 * Helper class to help handling of UI.
 */
public class UIHelper {
    public static boolean homeKeyPressed;
    private static boolean justLaunched = true;

    /**
     * Check if the app was just launched. If the app was just launched then
     * assume that the HOME key will be pressed next unless a navigation event
     * by the user or the app occurs. Otherwise the user or the app navigated to
     * the activity so the HOME key was not pressed.
     */
    public static void checkJustLaunced() {
        if (justLaunched) {
            homeKeyPressed = true;
            justLaunched = false;
        } else {
            homeKeyPressed = false;
        }
    }

    /**
     * Check if the HOME key was pressed. If the HOME key was pressed then the
     * app will be killed either safely or quickly. Otherwise the user or the
     * app is navigating away from the activity so assume that the HOME key will
     * be pressed next unless a navigation event by the user or the app occurs.
     * 
     * @param killSafely
     *            Primitive boolean which indicates whether the app should be
     *            killed safely or quickly when the HOME key is pressed.
     * 
     * @see {@link UIHelper.killApp}
     */
    public static void checkHomeKeyPressed(boolean killSafely) {
        if (homeKeyPressed) {
            killApp(true);
        } else {
            homeKeyPressed = true;
        }
    }

    /**
     * Kill the app either safely or quickly. The app is killed safely by
     * killing the virtual machine that the app runs in after finalizing all
     * {@link Object}s created by the app. The app is killed quickly by abruptly
     * killing the process that the virtual machine that runs the app runs in
     * without finalizing all {@link Object}s created by the app. Whether the
     * app is killed safely or quickly the app will be completely created as a
     * new app in a new virtual machine running in a new process if the user
     * starts the app again.
     * 
     * <P>
     * <B>NOTE:</B> The app will not be killed until all of its threads have
     * closed if it is killed safely.
     * </P>
     * 
     * <P>
     * <B>NOTE:</B> All threads running under the process will be abruptly
     * killed when the app is killed quickly. This can lead to various issues
     * related to threading. For example, if one of those threads was making
     * multiple related changes to the database, then it may have committed some
     * of those changes but not all of those changes when it was abruptly
     * killed.
     * </P>
     * 
     * @param killSafely
     *            Primitive boolean which indicates whether the app should be
     *            killed safely or quickly. If true then the app will be killed
     *            safely. Otherwise it will be killed quickly.
     */
    public static void killApp(boolean killSafely) {
        if (killSafely) {
            /*
             * Notify the system to finalize and collect all objects of the app
             * on exit so that the virtual machine running the app can be killed
             * by the system without causing issues. NOTE: If this is set to
             * true then the virtual machine will not be killed until all of its
             * threads have closed.
             */
            System.runFinalizersOnExit(true);

            /*
             * Force the system to close the app down completely instead of
             * retaining it in the background. The virtual machine that runs the
             * app will be killed. The app will be completely created as a new
             * app in a new virtual machine running in a new process if the user
             * starts the app again.
             */
            System.exit(0);
        } else {
            /*
             * Alternatively the process that runs the virtual machine could be
             * abruptly killed. This is the quickest way to remove the app from
             * the device but it could cause problems since resources will not
             * be finalized first. For example, all threads running under the
             * process will be abruptly killed when the process is abruptly
             * killed. If one of those threads was making multiple related
             * changes to the database, then it may have committed some of those
             * changes but not all of those changes when it was abruptly killed.
             */
            android.os.Process.killProcess(android.os.Process.myPid());
        }

    }
}
68 голосов
/ 19 января 2010

ДА!Вы наверняка можете закрыть свое приложение, чтобы оно больше не работало в фоновом режиме.Как и другие прокомментировали, finish() - это рекомендованный Google способ, который на самом деле не означает, что ваша программа закрыта.

System.exit(0);

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

Лично я НЕНАВИЖУ, когда выбираю в приложении «Выход», а это не так.Т действительно выход.

23 голосов
/ 26 апреля 2011

Вот как я это сделал:

Я просто поставил

Intent intent = new Intent(Main.this, SOMECLASSNAME.class);
Main.this.startActivityForResult(intent, 0);

внутри метода, который открывает действие, затем внутри метода SOMECLASSNAME, предназначенного для закрытия приложения, которое я поместил:

setResult(0);
finish();

И я поставил в свой основной класс следующее:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(resultCode == 0) {
        finish();
    }
}
18 голосов
/ 30 августа 2011

Просто чтобы ответить на мой собственный вопрос сейчас через столько времени (поскольку CommonsWare прокомментировал самый популярный ответ, сказав, что мы НЕ должны этого делать):

Когда я хочу выйти из приложения:

  1. Я начинаю свое первое действие (либо заставку, либо какое-либо действие, которое в данный момент находится внизу стека действий) с FLAG_ACTIVITY_CLEAR_TOP (которое завершит все остальные действия, начатые после него, что означает - все они),Просто сделайте так, чтобы эта активность была в стеке действий (не заканчивайте ее по какой-то причине заранее).
  2. Я звоню finish() по этой деятельности

Вот оно, работает вполнехорошо для меня.

10 голосов
/ 01 ноября 2013

Просто напишите этот код на кнопке EXIT click.

Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("LOGOUT", true);
startActivity(intent);

И в методе onCreate () вашего MainActivity.class введите следующий код в качестве первой строки,

if (getIntent().getBooleanExtra("LOGOUT", false))
{
    finish();
}
9 голосов
/ 19 января 2010

Невозможно использовать API-интерфейсы.Операционная система (Android) решает, когда процесс должен быть удален или оставлен в памяти.Это из соображений эффективности: если пользователь решает перезапустить приложение, то оно уже есть, без необходимости его загрузки в память.

Так что нет, это не только не рекомендуется , сделать это невозможно.

8 голосов
/ 15 апреля 2015

Для выхода из приложения:

Путь 1:

вызов finish(); и переопределение onDestroy();.Введите следующий код в onDestroy():

System.runFinalizersOnExit(true)

или

android.os.Process.killProcess(android.os.Process.myPid());

Путь 2:

public void quit() {
    int pid = android.os.Process.myPid();
    android.os.Process.killProcess(pid);
    System.exit(0);
}

Путь 3:

Quit();

protected void Quit() {
    super.finish();
}

Путь 4:

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

if (getIntent().getBooleanExtra("EXIT", false)) {
     finish();
}

Путь 5:

Иногда вызов finish() приведет к выходу только из текущего действия, а не из всего приложения.Однако для этого есть обходной путь.Каждый раз, когда вы запускаете activity, запускайте его, используя startActivityForResult().Когда вы хотите закрыть все приложение, вы можете сделать что-то вроде следующего:

setResult(RESULT_CLOSE_ALL);
finish();

Затем определить обратный вызов onActivityResult(...) каждого действия, поэтому, когда activity возвращается со значением RESULT_CLOSE_ALL, оно такжезвонки finish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode){
        case RESULT_CLOSE_ALL:{
            setResult(RESULT_CLOSE_ALL);
            finish();
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}
5 голосов
/ 19 января 2010

Вызов метода finish() для Activity оказывает желаемое влияние на текущую активность.

5 голосов
/ 19 января 2010

Так работает Windows Mobile ... ну ... когда-нибудь! Вот что Microsoft должна сказать по этому вопросу:

http://blogs.msdn.com/windowsmobile/archive/2006/10/05/The-Emperor-Has-No-Close.aspx (это печально, что я запомнил название поста в блоге с 2006 года? Я нашел статью в Google, выполнив поиск "у императора нет близких", смеется)

Короче говоря:

Если системе требуется больше памяти во время приложение находится в фоновом режиме, оно будет закройте приложение. Но если система не нужно больше памяти, приложение будет оставайтесь в оперативной памяти и будьте готовы вернуться быстро в следующий раз, когда пользователю нужно это.

Многие комментарии в на этот вопрос в O'Reilly говорят о том, что Android ведет себя примерно так же, закрывая приложения, которые некоторое время не использовались, только когда Android требуется память, которую они используют.

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

3 голосов
/ 26 ноября 2015

ни один из перечисленных выше ответов не работает хорошо в моем приложении

вот мой рабочий код

на вашей кнопке выхода:

Intent intent = new Intent(getApplicationContext(), MainActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
mainIntent.putExtra("close", true);
startActivity(mainIntent);
finish();

этот код должен закрыть любое другое действие и вывести MainActivity на первое место теперь на вашей основной деятельности:

if( getIntent().getBooleanExtra("close", false)){
    finish();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...