【问题标题】:How to start long running background task in android service如何在android服务中启动长时间运行的后台任务
【发布时间】:2012-05-18 00:37:03
【问题描述】:

阅读了开发者网站和 * 上关于 Android 服务的大部分可用文档后,我仍然对在单独的任务中运行服务的几个方面感到困惑。希望有人能让我走上正轨。

假设我们有简单的服务框架,例如

public class HliService extends Service {

    @Override
    public void onCreate() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // If we get killed, after returning from here, restart
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // We don't provide binding, so return null
        return null;
    }

    @Override
    public void onDestroy() {
    }
}

在清单中,我有

<service android:name=".HliService" android:process=":HLI_Comms"/>

以便服务在自己的线程中运行。

服务的目的是提供一个后台任务来进行通信 到使用 TCP 套接字的设备并做一些其他的事情。冒着忽略电池问题等的风险,基本上我希望它永远运行。

类似

// Method that communicates using a TCP socket, and needs to send
// information back to the activity and receive messages from activity
// not shown here.
private void dummytask() {

    boolean keepGoing = true;
    while (keepGoing) {
        // do useful stuff in here
        // sets keepGoing false at some point
    }
    stopSelf();
}

启动此方法/任务的最佳方式是什么?

我查看了开发人员站点中使用消息处理程序和循环器的代码,我只了解了一部分,但它似乎非常复杂,可能超出了我的要求?

我不相信我可以从onCreate()onStartCommand() 调用此方法,因为从系统调用时两者都不会完成?我应该用计时器还是闹钟启动它?

我需要添加一个消息处理程序来与 gui 活动进行通信,但是由于我在另一个线程中启动服务(通过清单“进程”指令),我是否需要使用 AIDL 来代替?

我也研究过使用 AysnchTask 而不是扩展 Service,但它似乎更适合运行任务然后终止。

【问题讨论】:

  • while (keepGoing) - 如果这是在另一个线程中,而不是设置 keepGoing 为 false keepGoing 必须是 volatile - 在 Java 内存模型上读取
  • 请看这个答案,这可能会对你有所帮助。 [在此处输入链接描述][1] [1]:*.com/a/13783477/2165080

标签: android service background


【解决方案1】:

让服务在自己的线程中运行。

这会将服务置于自己的进程中。这通常是要避免的,因为它会消耗额外的 RAM 和 CPU(对于 IPC)。您可以通过创建Thread 或任何数量的其他方式来创建线程,其中大部分已经在 J​​ava 中使用了十年左右。

冒着忽略电池问题等的风险,基本上我希望它永远运行。

服务几乎不可能永远运行。用户或操作系统最终会摆脱您的服务。

启动此方法/任务的最佳方式是什么?

从后台线程调用dummytask()

我需要改用 AIDL 吗?

没有。您的服务可以广播Intent,或调用活动提供的PendingIntent,或通过活动提供的Messenger 发送Message,等等。最好是使用LocalBroadcastManager 从Android 支持包,但它无法跨越进程边界,迫使您选择更昂贵的通信选项。

【讨论】:

  • 好的 - 谢谢@CommonsWare。我也看过这种方法,但也不确定实施它的某些方面——我会做更多的研究,也许会发布一个后续问题。我会听取您关于不使用“过程”的建议。顺便说一句,我确实知道该服务实际上不会永远运行 - 这只是一种简化。再次感谢。
【解决方案2】:

我认为您可以使用IntentService,通过设置一个带有PendingIntent 的(常规)警报(AlarmManager.setRepeating)来运行它。您可以通过从 IntentService 广播 Intent 并通过 BroadcastReceiver 在您的 UI 中接收它来通知 UI。

【讨论】:

  • 谢谢@omoling - 这不是更适合只运行一个小任务然后终止,而不是启动一个长时间运行的进程吗?
最近更新 更多