Android 应用在被杀死 (ICS) 时不会调用“onDestroy()”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11473849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:47:02  来源:igfitidea点击:

Android app doesn't call "onDestroy()" when killed (ICS)

androidandroid-4.0-ice-cream-sandwichondestroy

提问by The Good Giant

I'm developing an android app using bluetooth communication (using a propetary protocol) and I need to catch the moment when the app is killed.

我正在使用蓝牙通信(使用专有协议)开发一个 android 应用程序,我需要抓住应用程序被杀死的那一刻。

I wanted to use the "onDestroy()" method but it isn't called every time the app is killed. I noticed that it is called when I press the back button and, only sometimes, when I kill the app from the task manager.

我想使用“onDestroy()”方法,但每次应用程序被杀死时都不会调用它。我注意到当我按下后退按钮时会调用它,并且只有在有时,当我从任务管理器中杀死应用程序时才会调用它。

The question is: How can I catch the moment before the app is killed?

问题是:我怎样才能抓住应用程序被杀死之前的那一刻?

Here is the code I tried to use:

这是我尝试使用的代码:

@Override
public void onDestroy() {
    sendMessage(msg);
    Log.d("SampleApp", "destroy");
    super.onDestroy();
}

@Override
public void finish(){

    sendMessage(msg);
    Log.d("SampleApp", "finish");
    super.finish();
}

Unfortunately finish() is never called and onDestroy isn't called every time I close the app from the task manager.

不幸的是,每次我从任务管理器关闭应用程序时,finish() 都不会被调用,并且 onDestroy 也不会被调用。

How can I handle this?

我该如何处理?

采纳答案by Raghav Sood

As stated in the documentation here, there is no guarantee that onDestroy() will ever be called. Instead, use onPause()to do the things you want to do whenever the app moves into the background, and leave only that code in onDestroy() that you want run when your app is killed.

正如此处的文档中所述,不能保证 onDestroy() 会被调用。相反,当应用程序进入后台时,使用onPause()来做你想做的事情,并且只在 onDestroy() 中留下你想要在你的应用程序被终止时运行的代码。

EDIT:

编辑:

From your comments, it seems that you want to run some code whenever your app goes into the background, but not if it went into the background because you launched an intent. AFAIK, there is no method in Android that handles this by default, but you can use something like this:

从您的评论来看,您似乎希望在您的应用程序进入后台时运行一些代码,但如果由于您启动了一个意图而进入后台,则不会。AFAIK,默认情况下,Android 中没有处理此问题的方法,但您可以使用以下方法:

Have a boolean like:

有一个布尔值,如:

boolean usedIntent = false;

Now before using an intent, set the boolean to true. Now in your onPause(), move the code for the intent case into an if block like this one:

现在在使用意图之前,将布尔值设置为 true。现在在您的 onPause() 中,将意图案例的代码移动到像这样的 if 块中:

if(usedIntent)
{
//Your code
}

Finally, in your onResume(), set the boolean to false again so that it can deal with your app being moved into the background by a non intent means properly.

最后,在您的 onResume() 中,再次将布尔值设置为 false,以便它可以正确处理通过非意图方式将您的应用程序移入后台的情况。

回答by Devunwired

Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.

如果您的应用程序通过外部方式终止进程(即因内存原因而终止或用户强制停止应用程序),您的应用程序将不会收到任何额外的回调。当您的应用程序进入后台进行应用程序清理时,您将不得不处理收到的回调。

finish()is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.

finish()仅当用户从您的 Activity 中按下 BACK 按钮时,系统才会调用它,尽管应用程序通常会直接调用它以离开一个 Activity 并返回到上一个 Activity。这在技术上不是生命周期回调。

onDestroy()only gets called on an Activity as a result of a call to finish(), so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes through onPause()and onStop().

onDestroy()仅在调用 Activity 时才会调用 Activity finish(),因此主要仅在用户点击 BACK 按钮时调用。当用户点击 HOME 按钮时,前台 Activity 只会通过onPause()onStop()

This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a wholehas been brought forward or moved backward.

这意味着 Android 不会向 Activity 提供太多反馈来区分用户回家与移动到另一个 Activity(从您的应用程序或任何其他);Activity 本身只知道它不再在前台。Android 应用程序更像是一个松散的活动集合,而不是一个紧密集成的单一概念(就像您在其他平台上可能习惯的那样),因此没有真正的系统回调来了解您的应用程序作为一个整体何时被提出或移动落后。

Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound Serviceinside of your application that every Activitybinds to while active (i.e. between onStart()and onStop()). What this provides you is the ability to leverage the fact that a bound Serviceonly lives as long as clients are bound to it, so you can monitor the onCreate()and onDestroy()methods of the Serviceto know when the current foreground task is not part of your application.

最终,我会敦促您重新考虑您的应用程序架构,如果它依赖于您的应用程序中的 ANY Activity 是否在前台的知识,但根据您的需要,可能有其他对框架更友好的方法来实现这一点。一种选择是Service在您的应用程序内部实现一个绑定,每个Activity绑定到活动时(即在onStart()和之间onStop())。这是什么为您提供是利用一个事实,即绑定的能力Service只活只要客户端绑定到它,这样你就可以监控onCreate()onDestroy()方法服务的认识在当前前台任务是不是你的应用程序的一部分。

You might also find this articlewritten by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.

您可能还会发现Dianne Hackborn 撰写的这篇文章很有趣,它更详细地介绍了 Android 架构以及 Google 认为应该如何使用它。

回答by Naveen Kumar M

I just resolved a similar kind of issue.

我刚刚解决了类似的问题。

Here is what you can do if its just about stopping servicewhen application is killed by swiping from Recent app list.

如果只是在通过从“最近的应用程序列表”中滑动而终止应用程序时停止服务,您可以执行以下操作。

Inside your Manifest file, keep flag stopWithTaskas truefor Service. Like:

里面你的清单文件,守旗stopWithTasktrue维修。喜欢:

<service
    android:name="com.myapp.MyService"
    android:stopWithTask="true" />

But as you say you want to unregister listeners and stop notification etc, I would suggest this approach:

但是正如您所说,您想取消注册侦听器并停止通知等,我建议使用这种方法:

  1. Inside your Manifest file, keep flag stopWithTaskas falsefor Service. Like:

    <service
        android:name="com.myapp.MyService"
        android:stopWithTask="false" />
    
  2. Now in your MyServiceservice, override method onTaskRemoved. (This will be fired only if stopWithTaskis set to false).

    public void onTaskRemoved(Intent rootIntent) {
    
        //unregister listeners
        //do any other cleanup if required
    
        //stop service
        stopSelf();  
    }
    
  1. 里面你的清单文件,守旗stopWithTaskfalse维修。喜欢:

    <service
        android:name="com.myapp.MyService"
        android:stopWithTask="false" />
    
  2. 现在在您的MyService服务中,覆盖 method onTaskRemoved。(仅当stopWithTask设置为 时才会触发false)。

    public void onTaskRemoved(Intent rootIntent) {
    
        //unregister listeners
        //do any other cleanup if required
    
        //stop service
        stopSelf();  
    }
    

Refer this questionfor more details, which contains other part of code, too.

有关更多详细信息,请参阅此问题,其中也包含代码的其他部分。

  1. Start service like below
  1. 像下面这样启动服务

startService(new Intent(this, MyService.class));

开始服务(新意图(这个,MyService.class));

Hope this helps.

希望这可以帮助。