应用关闭后,Android服务执行AsyncTask

时间:2015-11-12 23:20:56

标签: android android-asynctask android-service android-broadcast intentservice

我目前正在开发Android应用程序。其中一个要求是广泛记录应用程序的使用方式。更具体地说,应该记录用户关闭应用的时间。此日志记录包含服务器交互。关于这个具体要求,我偶然发现:

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
  • IntentService方法中启动onTaskRemoved(在AsyncTask方法中启动onHandleIntent)解决了这个问题。
  • BroadcastReceiver与本地广播(LocalBroadcastManager#sendBroadcast)结合使用也不起作用(我仔细检查了广播接收器是否已被有效注册为发送广播的接收方)。

修改

我还看了Application类中的回调: - onTerminate:此方法仅在模拟环境中调用,因此无用 - onTrimMemory(int):此方法可用于检测应用程序何时进入后台,但在应用程序退出时没有明显的大小写。

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

1 个答案:

答案 0 :(得分:0)

首先:在Android中,您不能保证执行您的要求。期。系统可以随时使用gc你的课程或杀死你的过程。此外,Android概念并没有真正具有“关闭应用程序”操作的概念,就像网站没有它一样。所以在你继续阅读之前,我敦促你重新考虑你的要求。

话虽如此。以下是一些提示: 我对Service#onTaskRemoved(Intent)的理解是,它只会在您通过任务切换器终止应用程序时执行,因此我不知道这对您是否有用。在你的实例中,我会在应用程序对象中保留一个活动引用计数器(每个onResume()为+1,对于任何活动的每个onPause()都为-1)。有了这个,您可以检查您的用户是否具有活动的UI。通常,如果你按下最后一个活动,那就是接近“关闭”应用程序的范例。然后只需从应用程序对象启动您的任务(这可能是获取gc的最后一个),或者如果这不起作用,请尝试未绑定服务您可以生成的最多解耦组件。< / p>

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