如何知道我的应用程序何时被终止?

98

我需要知道用户何时结束我的应用程序(强制停止)。 我一直在阅读Android生命周期,其中包括onStop()onDestroy()函数,这些与用户在我的应用程序上结束的每个活动相关,但不是当用户强制停止或终止我的应用程序时。

有没有办法知道用户何时杀死应用程序?


1
这是不可能的。请参见https://dev59.com/hmQo5IYBdhLWcg3wfPbK。 - transporter_room_3
为什么您需要知道他们何时结束应用程序?如果您的应用程序编码良好,您其实并不在乎他们是否结束了它。 - npace
2
项目规格需要知道用户何时关闭此应用程序。我不喜欢这种方法,但我必须编写他们要求的代码。 - Darknoe
10
无论一个应用程序的编码质量如何,您可能希望了解它何时被挂起、终止或发生任何其他状态变化,仅供信息参考。@npace - Vicenç Gascó
3
好的,我会尽力进行翻译。原文中所指的“well coded”是指“以不依赖当前Android系统功能为前提进行编码”,因此,你可能想知道这一点,但实际上这并不是完全可能的。 - npace
9个回答

153

我已经找到一种方法来完成这个......

  1. 创建一个像这样的服务

    public class OnClearFromRecentService extends Service {
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d("ClearFromRecentService", "Service Started");
            return START_NOT_STICKY;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d("ClearFromRecentService", "Service Destroyed");
        }
    
        @Override
        public void onTaskRemoved(Intent rootIntent) {
            Log.e("ClearFromRecentService", "END");
            //Code here
            stopSelf();
        }
    }
    
  2. 将此服务在Manifest.xml中注册,如下所示

  3. <service android:name="com.example.OnClearFromRecentService" android:stopWithTask="false" />
    
    然后在你的启动页活动上启动此服务。
    startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
    

现在,每当您从Android最近的应用程序中清除您的应用程序时,那么这个方法 onTaskRemoved() 将会被执行。

注意:在Android O+中,此解决方案仅在应用程序全时在前台运行时有效。在超过1分钟的后台运行后,OnClearFromRecentService(以及所有其他正在运行的服务)将被系统自动强制停止,因此不会执行onTaskRemoved()方法。


13
我最近按照这里描述的方式添加了onTaskRemoved()方法,并且它有效了。但是在华为和小米设备上却不行。有什么想法是为什么吗? - Alon Minski
2
这很好。为什么onTaskRemoved没有声明为override? - Florian Doyon
1
可以将数据保存在那里吗?例如保存到SQLite。 - K.Sopheak
1
我最近添加了一个类似于此处描述的onTaskRemoved(),并且它可以正常工作。除了在华为和小米设备上。由于某种原因,在这些设备上这个方法从未被调用过。你有什么想法吗?我也遇到了同样的问题,请帮帮我。 - Rajaji subramanian
2
非常有帮助,不过需要测试华为或小米手机。正如@Alon Minski所说。 - Vrajesh
显示剩余18条评论

30

无法确定进程何时被终止。 来自如何检测Android应用程序是否被强制停止或卸载?

当用户或系统强制停止您的应用程序时,整个进程会被简单地终止。没有回调通知您发生了这种情况。

当用户卸载应用程序时,首先终止进程,然后删除您的apk文件和数据目录,以及包管理器中的记录,告诉其他应用程序您已注册哪些意图过滤器。


23
好的。太好了。这是不可能的。那么作为开发者,我们能做些什么来预防我们的应用被杀死?当我重新打开应用程序时,经常会出现奇怪的行为,尤其是在长时间未使用后。 - Josh

5
创建一个Application类
onCreate()
Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
onLowMemory()
This is called when the overall system is running low on memory, and actively running processes should trim their memory usage.
onTerminate()
This method is for use in emulated process environments.

即使您的应用程序被杀死或强制停止,Android也会重新启动您的Application类。

当应用程序被杀死时,Application类能够检测到吗? - ondermerol
如果应用程序正常关闭,我们可以检测到原因,这意味着由于低内存或Android清理应用程序进程。 - rajahsekar
如果被用户杀死,那么我们就无法检测到它了吗? - ondermerol
9
我认为OP的意思是如何检测应用程序实例即将停止/被终止。onTerminate仅在模拟环境中起作用。 - BearDroid

2
对于某些情况,您可以创建启动画面页面来确定应用程序是否已被系统杀死。
它基本上是一个带有意图过滤器main/launcher的屏幕,并且将被完成并切换到主活动。
因此,每次用户访问splashScreen时,它都会显示该应用程序以前已经被杀死,并且您可以做任何您想要处理的事情。
示例代码:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="id.gits.yourpackage">

    <application
        android:name=".App">
        <activity android:name=".SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

SplashActivity:

class SplashActivity : AppCompatActivity() {
    override fun onCreate() {
        super.onCreate()
        doSomethingAfterAppKilled()
    }
}

请发送代码的截图。 - Arbaz.in
1
@Arbaz.in,我刚刚编辑了答案。 - nashihu

1
在深入研究这个问题后,我找到了一个可能会对您有所帮助的解决方案:
您需要检查所有活动都继承自您的BaseActivity的onDestroy方法,以确定堆栈中最后一个运行的活动是否来自您的软件包。代码如下:
ActivityManager activityManager = (ActivityManager) getSystemService( ACTIVITY_SERVICE );

List<ActivityManager.RunningTaskInfo> taskList = activityManager.getRunningTasks( 10 );

if ( !taskList.isEmpty() )
    {
     ActivityManager.RunningTaskInfo runningTaskInfo = taskList.get( 0 );
      if ( runningTaskInfo.topActivity != null && 
              !runningTaskInfo.topActivity.getClassName().contains(
                    "com.my.app.package.name" ) )
         {
        //You are App is being killed so here you can add some code
         }
    }

1
我找到了一种可以检测应用程序(包含Activity场景)关闭的方法:使用ActivityLifecycleCallbacks来计数活动的数量。
有几种情况:
- 用户关闭(使用应用程序切换器):计数活动数量/任务栈等。 - (未指定)Android Framework关闭(低内存等): - (未指定)Native关闭(Process.kill杀死信号):使用本机。
class StarterApplication: android.app.Application() {
var counterActivityCreate = 0
override fun onCreate() {
    super.onCreate()
    Log.d(TAG, "onCreate: ")

    registerActivityLifecycleCallbacks(object: android.app.Application.ActivityLifecycleCallbacks{
        override fun onActivityCreated(activity: android.app.Activity, savedInstanceState: android.os.Bundle?) {
            Log.d(TAG, "onActivityCreated: ${activity.javaClass.name}")
            counterActivityCreate++
        }

        override fun onActivityStarted(activity: android.app.Activity) {
            Log.d(TAG, "onActivityStarted: ${activity.javaClass.name}")
        }

        override fun onActivityResumed(activity: android.app.Activity) {
            Log.d(TAG, "onActivityResumed: ${activity.javaClass.name}")
        }

        override fun onActivityPaused(activity: android.app.Activity) {
            Log.d(TAG, "onActivityPaused: ${activity.javaClass.name}")
        }

        override fun onActivityStopped(activity: android.app.Activity) {
            Log.d(TAG, "onActivityStopped: ${activity.javaClass.name}")
        }

        override fun onActivitySaveInstanceState(activity: android.app.Activity, outState: android.os.Bundle) {
            Log.d(TAG, "onActivitySaveInstanceState: ${activity.javaClass.name}")
        }

        override fun onActivityDestroyed(activity: android.app.Activity) {
            Log.d(TAG, "onActivityDestroyed: ${activity.javaClass.name}")
            counterActivityCreate--
            if(counterActivityCreate == 0){
                Log.d(TAG, "onActivityDestroyed: all activity destroyed")

            }
        }

    })
}

这对于用户关闭应用程序来说行不通,对吗? - Divesh
@Divesh 我已经验证了第一个情况:用户Kill,剩下的两种情况还没有被验证。 - Hpbbs

0

我找到了适用于小米手机的解决方案,你需要创建一个类,例如"MyObserver",并在onCreate方法中调用它,代码如下:getLifecycle().addObserver(MyObserver(this))。

class MyObserver(var context: Context) : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun disconnect() {
        Log.e("APP", "killed")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun pause(){
        Log.e("APP","Paused") //para pausa
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun resume(){
        Log.e("APP","Resumed") //para retorno de pausa
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop(){
        Log.e("APP","Stopped") // para cambio de actividad
    }
}

谷歌像素手机无法正常工作。 - undefined

0

这可能会帮助许多人,他们想知道应用程序是否已终止

最好的方法是将数据保存在一个静态变量中

例如:public static string IsAppAvailable;

静态变量的特殊之处在于,静态变量中的数据在应用程序在前台或后台时都会保留,一旦应用程序被杀死,静态变量中的数据就会被清除。基本上,当应用程序重新创建时,静态变量会被重新初始化。

创建一个静态类文件,比如Const

namespace YourProject
{
    public static class Const
    {
        public static string IsAppAvailable;
     }
}

在MainActivity中

   protected override void OnResume()
    {
       if(string.IsNullOrWhiteSpace(Const.IsAppAvailable))
       {
          //Your app was terminated
       }
       Const.IsAppAvailable = "Available" 
    }

希望对开发人员有所帮助 :) 愉快编码


那么如何检测常量值何时被冻结? - famfamfam

-4

我有一个替代的想法。我和你一样遇到了同样的问题,上面的方法都没有解决我的问题:“当用户完全关闭应用程序时,我想清除整个应用程序中保存的所有数据”。

因此,我在Application类中添加了clear()和clear saved data(从shared preference或tinyDB中)。


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