如何在Android服务中启动长时间运行的后台任务

7

我已经阅读了开发者网站和StackOverflow上大部分关于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吗?
我还尝试使用AsyncTask而不是扩展Service,但它似乎更适合运行任务然后终止。

while (keepGoing) - 如果这段代码在另一个线程中,而不是将 keepGoing 设置为 false 的线程,则 keepGoing 必须是 volatile 的。请阅读Java内存模型的相关知识。 - Mr_and_Mrs_D
请查看此答案,可能会对您有所帮助。链接描述在这里 - Ashekur Rahman Molla Asik
2个回答

2

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

这将把服务放到它自己的进程中。通常情况下,应该避免这样做,因为它会消耗额外的RAM和CPU(用于IPC)。您可以通过创建一个Thread或其他许多Java已有十年左右的方式来创建一个线程。

尽管忽略电池问题等,但基本上我希望它能一直运行下去。

对于一个服务来说,它几乎不可能永远运行。用户或操作系统最终会摆脱你的服务。

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

从后台线程调用dummytask()

我需要使用AIDL吗?

不需要。您的服务可以广播一个Intent,或调用由活动提供的PendingIntent,或通过由活动提供的Messenger发送Message等。最好使用Android支持包中的LocalBroadcastManager,但这将无法跨越进程边界工作,迫使您选择更昂贵的通信选项。


好的 - 感谢 @CommonsWare。我也看过那种方法,但对于实现它的某些方面还不确定 - 我会进行更多研究,或许会发布跟进问题。我会采纳你的建议,不使用 "process"。顺便说一句,我知道服务实际上不会永远运行 - 这只是一个简化。再次感谢。 - SteveJP

0

我认为你可以使用一个IntentService,通过设置一个(常规)闹钟(AlarmManager.setRepeating)和其中的PendingIntent来运行它。您可以通过从IntentService广播一个意图并通过BroadcastReceiver在UI中接收它来通知UI。


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

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