关闭应用程序并在Android上启动主屏幕


76

我有两个不同的活动。第一个启动第二个。在第二个活动中,我打电话System.exit(0)以强制关闭应用程序,但第一个活动将自动显示,而不是应用程序返回到主屏幕。如何避免这种情况,并使应用程序返回主屏幕?


由于堆栈中有多个活动,因此System.exit(?)将重新启动它。(我认为)
Yousha Aleayoub

Answers:


45

您应该真正考虑不退出该应用程序。这不是Android应用程序通常的工作方式。


2
由于在android应用中没有退出。有没有一种方法可以遍历应用程序的所有活动,以便在每个活动上调用Finish(),即完成所有已启动的活动?
阿鲁莎2010年

2
为什么需要这样做?活动是否由于注销或其他某种情况而处于不适当的状态?您可以在其中进行检查onResume,然后再finish进行活动。
詹姆斯

2
作为用户和开发人员,问题在于Android中的自动内存清理效果不佳。那里有太多“表现欠佳”的应用程序,以至我的手机确实开始耗尽内存,并且当它变低时,UI开始变得口吃。(当前)HTC Desire具有较高的规格。我认为这就是为什么我和其他人有时会问这个问题的原因。
理查德·勒·梅苏里尔

1
@Richard:更好的解决方案是在应用程序上调用onPause时停止所有活动吗?应用程序造成速度减慢的唯一方法是,如果在不需要时暂停了它们,但仍在运行AsyncTasks等。例如,游戏应在onPause之后退出其主循环。(而且从循环中退出还不算在内。)
idbrii 2011年

2
@pydave:我同意你的看法。但是关于这种类型的话题似乎有很多争论,我正在分享一些“现实世界”的开发人员和用户体验。事实是,由于可用内存减少,此刻我的手机速度显着下降。可以这么说,看来我有“后台”应用程序,这些应用程序正在耗尽该内存。如果我杀死了这些应用程序,我会体验到我的设备可以加快速度。这让我认为,如果1)开发人员可以编写代码以完全杀死一个进程并释放其内存,或者2)android GC的运行情况好于当前状态,那将是很好的选择。ymmv
Richard Le Mesurier

88

简短的回答:呼叫moveTaskToBack(true)你的Activity,而不是System.exit()。这将隐藏您的应用程序,直到用户想要再次使用它为止。

更长的答案从另一个问题开始:为什么要取消您的应用程序?

Android OS处理内存管理和进程等,因此我的建议只是让Android为您担心。如果用户想离开您的应用程序,则可以按“主页”按钮,您的应用程序将有效地消失。如果手机以后需要更多内存,则操作系统将终止您的应用程序。

只要您适当地响应生命周期事件,您和用户都不需要关心您的应用程序是否仍在运行。

因此,如果您想隐藏应用程序调用moveTaskToBack()并让Android决定何时终止它。


4
有关戴夫的说法更多的信息,看看stackoverflow.com/questions/2033914/...
CommonsWare

杀死应用程序有合法用途-例如,我正在进行内测,如果用户没有适当的密码,则需要关闭我的应用程序。
马特·里昂斯

4
@Matt:为什么不只是在密码屏幕上停止用户?如果他们无法完成该任务,那么为什么需要强制关闭应用程序?
idbrii 2011年

一种特殊情况是用户按下“后退”按钮退出应用程序。在这种情况下,默认的onKeyUp()处理函数将执行finish()。但是我的经验是,finish()不能总是足够地清理内存,而System.exit(0)可以。因此,在这种特定情况下,用户实际上已经对您的应用说了再见,并且暗中说她不想保留任何状态,我发现调用System.exit(0)可以更好地进行清理向上。
卡尔

53

下面给出实现此目的的最简单方法(不影响Android的本机内存管理。不涉及进程杀死)。

  1. 使用以下意图启动活动:

    Intent intent = new Intent(this, FinActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    finish();
    
  2. 在目标活动中FinActivity.class,在中调用finish()onCreate

步骤说明:

  1. 您创建一个擦除所有其他活动(FLAG_ACTIVITY_CLEAR_TOP)并删除当前活动的意图。

  2. 活动会自我毁灭。另一种选择是您可以在finActivity中创建启动屏幕。这是可选的。


3
您是否不想在finish()之前使用startActivity()?
某处某人

FinActivity必须是您的RootActivity对吗?使用该标志将FinActivity.class按照文档developer.android.com/reference/android/content/…中所述重新启动您。
2014年

像魅力一样工作:)
Radhey

这确实退出了活动和服务,但是调试器仍然显示线程在后台运行,并且仍然显示我的应用程序按下多任务按钮。
斯蒂芬M-罢工

20

Android具有根据其文档安全关闭应用程序的机制。在退出的最后一个Activity(通常是应用程序启动时首先出现的主要Activity)中,将几行放在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键事件保留 给自己,以便开发人员无法阻止用户离开其应用程序。


4
查看AOSP源代码,现在不赞成使用此方法:@不赞成使用此方法是不安全的。
Artem Russakovskii 2011年

9

您还可以在标记中为第一个活动指定noHistory =“ true”,或者在启动第二个活动后立即完成第一个活动(如David所说)。

AFAIK,“强制关闭”将终止承载运行您的应用程序的JVM的进程,而System.exit()终止运行您的应用程序实例的JVM。两者都是突然终止的形式,不建议用于正常的应用程序流程。

正如捕获异常以覆盖程序可能执行的逻辑流程一样,也是不可取的。


无法正确关闭应用程序并且所有活动仍处于打开状态?
阿鲁莎2010年

2
不,Android并没有真正的“应用程序”概念。您的应用是“活动”的集合。如果您不想在完成第二个活动后返回到第一个活动,则应使用上述noHistory属性。
Christopher Orr 2010年


9

我使用这种方法关闭活动!

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

8

当您启动第二个活动时,finish()第一个活动将立即:

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

1
我不想系统地完成第一个活动,仅当我调用System.exit(0)时。这是正常现象吗?应用程序管理器中的强制关闭按钮如何工作?
阿鲁莎2010年

1
哦。那我误读了你的问题,对不起。这不是标准android应用生命周期的样子。FC按钮使用类似的功能android.os.Process.killProcess(android.os.Process.myPid());,这与您通常不希望退出应用程序的方式类似。但是您可以使用它,也可以考虑研究startActivityForResultfinishActivity,并且仅在第二个活动以某个响应代码结束时才构建第一个活动结束的地方。
David Hedlund 2010年

6

android.os.Process.killProcess(android.os.Process.myPid()); 工作正常,但是建议让Android平台担心内存管理:-)


4

您不能执行System.exit(),这是不安全的。

您可以执行以下操作:Process.killProcess(Process.myPid());


您需要正确的权限-<uses-permission android:name =“ android.permission.KILL_BACKGROUND_PROCESSES” />
Kevin Parker

适用于以设备所有者身份运行的我的应用程序。不需要新的权限。仍然离开的是多任务视图。
斯蒂芬M-罢工

4

我用这个:

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

这对我来说很好。


4

使用finish方法。这是越来越简单的方法。

this.finish();

2

请记住,在使用使用持久套接字连接的应用程序时,该finish()方法不会释放连接。在正常情况下,这finish()是最好的选择,但是如果您绝对需要退出某个应用并释放其正在使用的所有资源,请使用killProcess。我使用它没有问题。


2

使用startActivityForResult启动第二个活动,并在第二个活动中返回一个值,该值将在第一个活动的onActivityResult方法中关闭主应用程序。我认为这是Android的正确方法。


2

你错了。有一种杀死应用程序的方法。在具有超类Application的类中,我们使用一些字段,例如killApp。当启动启动屏幕(第一个活动)时onResume(),我们将field的参数设置为false killApp。在最后一次onResume()调用when的每个活动中,我们都这样调用:

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

进入屏幕的每个活动都必须调用onResume()。调用它时,我们必须检查我们的字段killApp是否为真。如果为true,则当前活动调用finish()。要调用完整动作,我们使用下一个构造。例如,在按钮操作中:

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

根据文档,android系统不会终止onStart(),onRestart()和onResume()等状态的活动。您的建议是绝对错误的!
anonim

2

请尝试以下方法。这个对我有用。

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

2

假设您有活动堆栈,例如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(即基本活动,这里是活动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是因为,如果活动处于活动状态,它将获得启动它的第一个意图。不是新的。有关更多详细信息-文档


1

其实很简单。

我这样做的方法是将标记保存在所有人都可以使用的静态变量中。然后,当我退出时,设置此标志,并且我所有的活动都检查该标志onResume。如果设置了标志,那么我将System.exit在该活动上发出on。

这样,所有活动都将检查该标志,并且如果设置了该标志,则将正常关闭。


1

这是我关闭应用程序所做的事情:在我的应用程序中,我有一个基础活动类,我添加了一个称为“ applicationShutDown”的静态标志。当我需要关闭应用程序时,将其设置为true。

在调用超级调用后的基本活动onCreate和onResume中,我测试了此标志。如果“ applicationShutDown”为true,则在当前Activity上调用finish。

这为我工作:

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

    }}

0

使用起始活动运行第二个活动以获得结果:

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

0

不建议这样做,但是您仍然可以使用它。如果您需要退出应用程序,最好使用此解决方案。

据我说,最好的解决方案是完成应用程序中的所有活动,如下所示。

步骤1.在mainactivity中维护一个静态变量。说,

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

0

我解决了一个类似的问题:MainActivity启动BrowserActivity,并且当用户在BrowserActivity中按Back时,我需要关闭该应用程序-不返回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;

看起来效果很好!:-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.