1

我目前正在开发Android应用程序。其中一个要求是大量记录有关应用程序的使用方式。更具体地说,应该记录关于何时用户关闭该应用。此日志记录由服务器交互组成。对于特定要求我偶然发现:Android服务在应用关闭后执行AsyncTask

Detect Application Exit(1)Detect application Exit (2)

这两个问题有一个公认的答案依靠Service#onTaskRemoved(Intent)

然而,在我的情况下,这种解决方案似乎并不奏效,即以这种方法启动的AsyncTask只有偶尔会执行。更具体地说,onPreExecute执行总是doInBackground不是。我在安装了Android 6(Marshmallow)的Nexus 5上测试了它。

public class SomeService extends Service { 

    @Override 
    public IBinder onBind(Intent aIntent) { 
    return null; 
    } 

    @Override 
    public void onTaskRemoved(Intent aRootIntent) { 
    new DoSomethingTask().executeOnExecutor(Asyntask.THREAD_POOL_EXECUTOR); 
    } 

    private static final class DoSomethingTask extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected void onPreExecute() { 
     Log.e(DoSomethingTask.class.getName(), "This is executed always"); 
    } 

    @Override 
    protected Void doInBackground(Void... aParams) { 
     Log.e(DoSomethingTask.class.getName(), "This appears to be executed only sometimes... "); 
     // here an actual call to a Rest API should be made to inform the server that the user has closed the application. 
    } 

    @Override 
    protected void onCancelled(Void result) { 
     super.onCancelled(result); 
     Log.e(DoSomethingTask.class.getName(), "Never invoked"); 
    } 

    @Override 
    protected void onCancelled() { 
     super.onCancelled(); 
     Log.e(DoSomethingTask.class.getName(), "Never invoked"); 
    } 
    } 
} 

这里是一切我试图在除了上述代码示例的概述:

  • 我已经onStartCommand选项(START_STICKY,START_NOT_STICKY等)没有成功尝试过各种。
  • 我也尝试在onTaskRemoved方法中重新启动服务,然后在onStartCommand中执行AsyncTask
  • onTaskRemoved方法(它在onHandleIntent方法中启动AsyncTask)中启动IntentService也解决了这个问题。
  • 使用BroadcastReceiver结合本地广播(LocalBroadcastManager#sendBroadcast)也不起作用(我仔细检查过广播接收器是否被有效注册为发送广播的接收器)。

编辑

我也采取了看看在Application类的回调: - onTerminate:此方法只调用在仿真环境中,因此没用 - onTrimMemory(int):这种方法可以用于检测应用程序何时进入后台,但应用程序退出时没有明确的情况。

我可以保留一个活动堆栈(将在Activity#onPause()等更新)。但是这需要在每个单独的Activity中进行相当多的工作,而不是上述Service方法,其只涉及在单个地方的干扰。

+0

您可以通过扩展Application类并重写onTerminate()onDestroy()onLowMemory()和类似的东西来做到这一点。 – napkinsterror

+0

我也试过,但我忘了在帖子中提到它。我现在已经在底部完成了,请参阅**编辑**部分。 –

回答

0

首先:在Android中,您无法保证执行您的要求。期。系统随时可以免费上课或终止您的程序。此外,Android概念并没有像网站没有的那样真正拥有“关闭应用程序”操作的概念。所以在你继续阅读之前,我敦促你重新考虑你的要求。

这就是说。以下是一些提示: 我对Service#onTaskRemoved(Intent)的理解是,只有在通过任务切换器杀死应用程序时才会执行该操作,所以我不知道这对您是否有用。在你的实例中,我会在应用程序对象中保留一个活动参考计数器(每个onResume()为+1,任何活动的每个onPause()为-1)。有了这个,你可以检查你的用户是否有活动的用户界面。通常情况下,如果您按下最后一个与“关闭”应用程序范例接近的活动。然后,只需从应用程序对象(这可能是获得gc的最后一个)开始执行任务,或者如果这不起作用,请尝试使用未绑定的服务您可以生成的最独立的组件。

另外,非常非常糟糕的解决方案正在覆盖对象(例如您的活动)中的finalize()方法。只有非常少的理由使用它,因为它会触发额外的gc循环,并且您的代码将在主线程上运行,但是如果该对象即将被gc化,则它是执行代码的一种方式。因此,Android团队使用它是不鼓励的,只有在你的头上有枪的时候才使用它。

相关问题