如何关闭Android应用程序?

Dan*_*ail 157 android

我想关闭我的应用程序,以便它不再在后台运行.

怎么做?这是Android平台上的好习惯吗?

如果我依赖"后退"按钮,它会关闭应用程序,但它会保留在后台.甚至有一个名为"TaskKiller"的应用程序只是为了在后台杀死这些应用程序.

Dan*_*OMS 139

Android有一个机制来根据其文档安全地关闭应用程序.在退出的最后一个Activity(通常是应用程序启动时首次出现的主Activity)中,只需在onDestroy()方法中放置几行.对System.runFinalizersOnExit(true)的调用可确保在应用程序退出时完成所有对象并收集垃圾. 如果您愿意,也可以通过android.os.Process.killProcess(android.os.Process.myPid())快速终止应用程序.执行此操作的最佳方法是在helper类中放置如下所示的方法,然后在需要杀死应用程序时调用它.例如,在根活动的destroy方法中(假设应用程序永远不会杀死此活动):

Android也不会通知HOME键事件的应用程序,因此在按下HOME键时无法关闭应用程序.Android会将HOME键事件保留 给自己,以便开发人员无法阻止用户离开其应用程序.然而,你可确定与HOME键是在假定一个辅助类标志设置为true,按下HOME键被按下,则改变标志设置为false事件发生时,显示的HOME键没有被按下,然后检查活动的onStop()方法中按下的HOME键.

不要忘记处理任何菜单和菜单启动的活动的HOME键.这同样适用于与搜索键.下面是一些示例类来说明:

下面是一个根活动的示例,它会在销毁时杀死应用程序:

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个抽象活动,可以扩展为处理扩展它的所有活动的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是处理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;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个帮助程序类的示例,它在整个应用程序中处理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());
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 没有生产应用程序应该使用此代码.没有生产应用程序应该调用`killApp()`中显示的任何代码,因为谷歌已经表明它将导致不可预测的行为. (17认同)
  • 非常感谢这个nfo.我正在和AndEngine一起制作游戏,当我打电话给完成时,即使在所有活动中,android仍然无法完全清理,当游戏重新启动时,它将完全被我的GL纹理全部搞砸了等等.因此在调查之后,我认为它是AndEngine,我开始意识到它必须是出错的原因,因为当我想要退出它时,android正试图保留这个过程.所有的评论"哦,你不应该打电话退出,它破坏了用户体验"是无稽之谈.天气申请应该保持开放....... (2认同)

Cam*_*ide 68

是!您当然可以关闭应用程序,使其不再在后台运行.像其他人一样评论的finish()是谷歌推荐的方式并不意味着你的程序已经关闭.

System.exit(0);
Run Code Online (Sandbox Code Playgroud)

那就是关闭你的应用程序,不让任何东西在后台运行.但是,明智地使用它,不要让文件打开,数据库句柄打开等.这些东西通常会通过finish()命令清理.

我个人讨厌当我在一个应用程序中选择退出时它并没有真正退出.

  • 谁决定你不是"应该",创造一个实际上没有退出的方法的人呢?如果用户不希望他们的应用程序关闭,那么第5个最受欢迎的付费应用程序将不会成为任务杀手.人们需要释放内存,核心操作系统无法完成工作. (74认同)
  • 绝对不建议使用System.exit(). (44认同)
  • 同意这是不明智的,但投票赞成提出问题的实际答案.我已经厌倦了听到"你真的不想这样做",没有后续解释.与iPhone相比,Android对于这些类型的东西的文档绝对是一场噩梦. (19认同)
  • 我不会争辩说这不是推荐的方式,但是你可以提供一个解决方案来保证应用程序立即退出后台吗?如果没有,则System.exit是直到Google提供更好方法的方式. (14认同)
  • 使用Android的任务杀手没有记忆优势.如果前台应用程序需要更多内存,Android将销毁并清除所有不在前台的应用程序.在某些情况下,Android甚至会重新打开使用任务杀手关闭的应用程序.Android将使用最近使用的应用程序填充所有不需要的内存,以减少应用程序切换时间.不要使用退出按钮构建应用程序.不要在ANDROID上使用任务管理器.http://geekfor.me/faq/you-shouldnt-be-using-a-task-killer-with-android/ http://android-developers.blogspot.com/2010/04/multitasking-android-way. HTML (11认同)
  • 嗯,不.你不应该*.使用黑客或肮脏的变通方法似乎不是我鼓励的事情. (3认同)

Ste*_*hen 23

这就是我这样做的方式:

我只是说

Intent intent = new Intent(Main.this, SOMECLASSNAME.class);
Main.this.startActivityForResult(intent, 0);
Run Code Online (Sandbox Code Playgroud)

在打开活动的方法内部,然后在SOMECLASSNAME的方法内部,该方法旨在关闭我放置的应用程序:

setResult(0);
finish();
Run Code Online (Sandbox Code Playgroud)

我把以下内容放在我的Main课程中:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(resultCode == 0) {
        finish();
    }
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ail 18

只是在这么多时间之后回答我自己的问题(因为CommonsWare评论了最流行的答案,告诉我们不应该这样做):

当我想退出应用程序时:

  1. 我启动了我的第一个活动(启动屏幕,或当前活动堆栈底部的任何活动)FLAG_ACTIVITY_CLEAR_TOP(这将退出在它之后启动的所有其他活动,这意味着 - 所有这些活动).只需在活动堆栈中进行此活动(不提前完成某些原因).
  2. 我打电话finish()给这个活动

这是它,对我来说效果很好.

  • 这应该足够了. (5认同)
  • 这实际上不会杀死你的应用程序.它仍将显示在应用列表中.我只是杀了你所有的活动. (3认同)

Lal*_*ale 10

只需在按钮EXIT点击上编写此代码即可.

Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("LOGOUT", true);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

MainActivity.classonCreate()方法中,将下面的代码写为第一行,

if (getIntent().getBooleanExtra("LOGOUT", false))
{
    finish();
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*ias 9

使用框架API是不可能的.操作系统(Android)可以自行决定何时删除进程或保留在内存中.这是出于效率的原因:如果用户决定重新启动应用程序,那么它已经存在,而不必将其加载到内存中.

所以不,不仅气馁,也不可能这样做.

  • 诚然.您还可以将手机撞到墙上,如果施加足够的压力,将终止所有打开的应用程序.我仍然不会推荐它.我已相应更新我的帖子. (6认同)
  • 你总是可以做类似Integer z = null的事情.z.intValue(); //最糟糕的答案 (4认同)

hit*_*141 8

对于退出app方式:

方式1:

呼叫finish();和覆盖onDestroy();.将以下代码放入onDestroy():

System.runFinalizersOnExit(true)
Run Code Online (Sandbox Code Playgroud)

要么

android.os.Process.killProcess(android.os.Process.myPid());
Run Code Online (Sandbox Code Playgroud)

方式2:

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

方式3:

Quit();

protected void Quit() {
    super.finish();
}
Run Code Online (Sandbox Code Playgroud)

方式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();
}
Run Code Online (Sandbox Code Playgroud)

方式5:

有时调用finish()只会退出当前活动,而不是整个应用程序.但是,有一个解决方法.每次启动时activity,都要使用它startActivityForResult().如果要关闭整个应用程序,可以执行以下操作:

setResult(RESULT_CLOSE_ALL);
finish();
Run Code Online (Sandbox Code Playgroud)

然后定义每个活动的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);
}
Run Code Online (Sandbox Code Playgroud)


And*_*y E 5

这就是Windows Mobile的工作方式......好吧......永远!以下是微软就此事所说的话:

http://blogs.msdn.com/windowsmobile/archive/2006/10/05/The-Emperor-Has-No-Close.aspx(从2006年开始我记得博客文章的标题是否令人难过?我通过搜索"皇帝没有关闭"在Google上发现这篇文章大声笑)

简而言之:

如果系统在应用程序处于后台时需要更多内存,它将关闭应用程序.但是,如果系统不需要更多内存,应用程序将保留在RAM中,并准备好在用户下次需要时快速返回.

O'Reilly这个问题中的许多评论表明,Android的行为方式大致相同,只有当Android需要他们正在使用的内存时,关闭那些尚未使用过的应用程序.

由于这是标准功能,因此将行为更改为强制关闭将改变用户体验.许多用户习惯于轻轻地解雇他们的Android应用程序,因此当他们在执行其他任务后解雇其中一个用户时,他们可能会相当沮丧,因为应用程序的状态被重置,或者需要更长的时间打开.我会坚持标准行为,因为它是预期的.


r1k*_*1k0 5

finish()Activity上调用方法会对当前活动产生所需的效果.

  • 不,不.它完成当前的Activity,而不是应用程序.如果你完成()任务堆栈上最底层的Activity,你的应用程序似乎会退出,但Android可能决定实际保留它,只要它认为合适. (14认同)