【问题标题】:Android Service execute AsyncTask after app closureAndroid服务在应用关闭后执行AsyncTask
【发布时间】:2015-11-12 23:20:55
【问题描述】:

我目前正在开发适用于 Android 的应用程序。要求之一是有关如何使用应用程序的大量日志记录。更具体地说,应该记录用户何时关闭应用程序。此日志记录由服务器交互组成。关于我偶然发现的具体要求:

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

这两个问题都有一个接受的答案,依赖于Service#onTaskRemoved(Intent)

在我的情况下,这个解决方案似乎不起作用,即在这个方法中启动的AsyncTasks 只是偶尔执行。更具体地说,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 方法中启动IntentService(在其AsyncTask 方法中启动AsyncTask)也不能解决问题。
  • BroadcastReceiver 与本地广播 (LocalBroadcastManager#sendBroadcast) 结合使用也不起作用(我仔细检查了广播接收器是否已有效注册为已发送广播的接收器)。

编辑

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

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

【问题讨论】:

  • 您可以通过扩展 Application 类并覆盖 onTerminate() onDestroy() onLowMemory() 和类似的东西来做到这一点。
  • 我也试过了,但我忘了在帖子里提到。我现在已经在底部完成了,请参阅 Edit 部分。

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


【解决方案1】:

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

话虽如此。以下是一些提示: 我对Service#onTaskRemoved(Intent)的理解是,只有通过任务切换器杀死应用才会执行,所以不知道对你有没有用。在您的实例中,我会在应用程序对象中保留一个 activity ref counter(每个 onResume() +1,任何活动的每个 onPause() -1)。有了这个,你可以检查你的用户是否有活跃的 UI。通常,如果您按下与范式“关闭”应用程序最接近的最后一个活动。然后从应用程序对象开始您的任务(这可能是最后一个获得 gc 的),或者如果这不起作用,请尝试 unbound service 您可以生成的最不耦合的组件。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 1970-01-01
    相关资源
    最近更新 更多