Android应用在被杀死时(ICS),不调用“onDestroy()”方法。

23

我正在开发一款使用蓝牙通信的安卓应用(使用专有协议),我需要在应用被杀死时捕获这一时刻。

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

问题是: 如何在应用程序被杀死之前捕捉到这一时刻?

以下是我尝试使用的代码:

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

@Override
public void finish(){

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

很不幸,无论何时我从任务管理器关闭应用程序,都没有调用finish()和onDestroy()。

我该如何处理这个问题?


你的意思是当应用程序被系统杀死时,当用户在设置中按下“强制停止”按钮,还是只是在查看您的Activity时按下HOME或BACK按钮? - devunwired
对我来说,两种方式都可以。我想要捕捉用户从任务管理器中杀死应用程序的时刻(或在冰淇淋三明治中长按主屏幕并从那里杀死应用程序),但也可以在用户查看我的活动时捕捉用户按HOME或BACK按钮的时刻。 - The Good Giant
你解决了吗? - Essam Mahdy
是的,使用下面的解决方案。 - The Good Giant
3个回答

17
根据这里的文档,不能保证onDestroy()方法一定会被调用。相反,使用onPause()方法来执行进入后台时需要做的事情,并且只在onDestroy()方法中留下那些在应用程序被杀死时需要运行的代码。
编辑:
根据您的评论,似乎您想在应用程序转入后台时运行某些代码,但如果因为启动意图而使其进入后台,则不运行该代码。据我所知,Android没有默认处理此功能的方法,但您可以使用类似以下代码的方法:
声明一个布尔变量:
boolean usedIntent = false;

现在,在使用意向(Intent)之前,将布尔值设置为true。现在在您的onPause()中,将意向情况(intent case)的代码移动到类似于以下代码块中的if语句中:

if(usedIntent)
{
//Your code
}

最后,在你的onResume()方法中,再次将该布尔值设置为false,以便可以正确处理非意图方式将应用程序移至后台。


我已经阅读了它,但问题是如果我把我的代码放在onPause()中,它也会在我在应用程序中启动新意图时执行。 相反,我希望只有在调用onPause返回到主屏幕时才发送我的消息。 - The Good Giant
只有主屏幕,或者像来电、用户查看通知时的另一个应用程序吗? - Raghav Sood
假设我想知道我的应用程序何时不再显示出来(因为无论什么原因它都进入了后台),但当启动一个意图时,我不想执行任何操作,因为我从我的应用程序中启动了一个新的意图。 - The Good Giant

16

如果应用程序因外部原因被终止(例如由于内存原因而被杀死或者用户强制停止应用程序),则您的应用程序将不会收到任何其他回调。在应用程序清理时,您必须利用当您的应用程序进入后台时所接收到的回调。

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

onDestroy()仅在通过调用finish()关闭Activity时才会在Activity上调用,因此主要是当用户按下BACK按钮时。当用户按下HOME按钮时,前台Activity只会经过onPause()onStop()

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

最终,我建议您重新考虑应用程序架构,如果它依赖于是否有任何Activity在前台的知识。但根据您的需求,可能有其他更友好的方式来完成这个任务。一种选择是在应用程序中实现一个绑定的Service,每个活动在活动期间(即在onStart()onStop()之间)绑定到该服务。这为您提供了利用绑定Service只在客户端绑定到它时才存在的事实的能力,因此您可以监视该服务的onCreate()onDestroy()方法,以了解当前前台任务是否属于您的应用程序。

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


我认为这是更合适的方式,我也认为他应该在应用程序中添加一个接口(或抽象类),以强制新添加的活动(或组件)定义此行为。 - Shirish Herwade
https://developer.android.com/guide/components/activities/activity-lifecycle.html - A.J.Bauer

5

我刚解决了类似的问题。

如果只是关于当应用程序被从最近应用列表中滑动掉导致服务停止时,你可以这样做:

在你的清单文件中,为服务保留标记stopWithTask,将其设置为true。例如:

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

但是,根据您的需求要取消注册侦听器和停止通知等操作,我建议采用以下方法:

  1. Inside your Manifest file, keep flag stopWithTask as false for Service. Like:

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

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

请参考这个问题,了解更多细节,其中包含其他代码部分。

  1. 按以下方式启动服务

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

希望这能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接