将startForeground()与意图服务一起使用

Fra*_*zzo 4 android

我正在尝试保持对屏幕开/关更改做出反应的服务。该服务将在一段时间内运行良好,但最终将被终止。我现在正尝试使用startForeground()来保持该进程运行,但是它似乎仍在消亡。我知道没有办法可以使进程永远存活,没有错误,但是我觉得我一定做错了,因为添加startForeground()不会增加进程的寿命。另外,作为旁注,由于未调用unregisterReceiver()(除非通过用户手动按下按钮进行手动操作),Logcat抱怨存在泄漏。.但是,由于我要完成的工作性质,接收方需要运行,直到明确告知要停止为止。

有什么建议么?

相关代码:

public class UpdateService extends IntentService {

        public UpdateService() {
        super(null);

    }

        @Override
        protected void onHandleIntent(Intent intent) {

            final int myID = 1234;


            Intent notificationintent = new Intent(this, Main.class);
            notificationintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            PendingIntent pendIntent = PendingIntent.getActivity(this, 0, notificationintent, 0);


            Notification notice = new Notification(R.drawable.icon_image, "***********", System.currentTimeMillis());


            notice.setLatestEventInfo(this, "*************", "***********", pendIntent);

            notice.flags |= Notification.FLAG_NO_CLEAR;
            startForeground(myID, notice);

            boolean screenOn = intent.getBooleanExtra("screen_state", false);


// Blah Blah Blah......


        }

        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return null;
        }

}
Run Code Online (Sandbox Code Playgroud)

Com*_*are 5

IntentServiceonHandleIntent()完成后自动关闭。发生某些事情时,它会执行一些简短的工作。通常,它的寿命不应超过几秒钟。

我将假定这与我在您在该区域的最后一个问题中的内容有关


应用程序其余部分将注册和取消注册BroadcastReceiver屏幕开/关事件-显然,从您的评论来看,这是一项活动。如果发生这些事情时您想要做的非常快(几毫秒的量级),只需在onReceive()中完成工作,然后完成它即可。

另一方面,如果您的工作量超过数毫秒,那么您将需要通过其他可以在后台线程上完成工作的工作来完成工作。例如,如果注册了的“应用程序其余部分中的内容” BroadcastReceiver确实是一项活动,则该活动可能只是产生了一项AsyncTask工作。

另一种可能性是使用IntentService。您选择在最后一个问题之前的工作中走这条路。我不知道为什么。无论如何,an IntentService像an一样AsyncTask,应该是短暂的组件-您通过发送命令startService(),它在中执行其工作onHandleIntent(),然后它消失了。

考虑到所有这些,让我们谈谈您的具体观点。


该服务将在一段时间内运行良好,但最终将被终止。

不清楚您认为“杀死”是什么意思。IntentService一旦onHandleIntent()返回,A 自动消失,理想情况下应在几秒钟内发生。

我现在正尝试使用startForeground()来保持该进程运行,但是它似乎仍在消亡。

同样,不清楚您认为“垂死”意味着什么。请记住,IntentService一旦屏幕关闭,仅存在an 并不会阻止CPU关闭,并且startForeground()与此无关。

另外,作为附带说明,由于未调用unregisterReceiver()(除非通过用户手动按下按钮进行手动操作),所以Logcat抱怨存在泄漏。

您还需要在用户退出活动之前注销接收器。调用registerReceiver()in onResume()unregisterReceiver()in 通常是一个好主意onPause()

  • 文档中没有任何内容指示“它的寿命不应超过几秒钟”。你在编造。如果服务愿意,它们可以永远存在。IntentService与实现普通Service类没有什么不同。 (13认同)
  • 从文档中:`如果声明该服务在前台运行(稍后讨论),那么它几乎永远不会被杀死`-http://developer.android.com/guide/components/services.html。相同的文档还说:“(IntentService)是最好的选择,如果您不需要您的服务同时处理多个请求。”但是,如果您想要长时间运行/无限期运行,则没有提到IntentService是一个不好的选择。服务。 (8认同)
  • 此外,如果您查看IntentService的源代码-http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app /IntentService.java-它说`(请求)可能需要很长时间`。即,没有提到几秒钟或几秒钟等。因此,看来IntentService前台确实是实现真正的持续服务的最佳和最简单的方法。 (7认同)
  • @AndroidDev:“如果愿意,服务可以永远存在” –除非它们不能,否则因为用户和/或操作系统会在需要时摆脱它们。“ IntentService与实现普通Service类没有什么不同” –您认为,`Integer`与普通`Object`类没有什么不同。 (6认同)
  • 拒绝投票的原因是:IntentService文档摘录:“所有请求都在单个工作线程上处理-*它们可能需要很长的时间*(并且不会阻塞应用程序的主循环),但是一次仅处理一个请求”。几秒钟左右什么也没说。因此,答案是关于IntentServices https://developer.android.com/reference/android/app/IntentService.html的误导 (2认同)

Gre*_*ryK 5

(更新)我认为可能存在以下情况:

1) IntentService状态的文档

服务会根据需要启动,使用工作线程依次处理每个Intent,并在工作耗尽时自行停止。

因此,可能是您的服务通常在onHandleIntent()完成后停止(特别是,正如您提到的,startForeground()不会增加进程的寿命)。

2)您可能会尝试检查它是否与设备进入休眠状态有关(或者您可能正在按计划启动设备并唤醒设备-在这种情况下,您可能需要获取WakeLock

3)在极少数情况下,系统仍然可以终止前台进程-因此,如果您进行大量分配(确实很多)和其他一些工作onHandleIntent()(而不是代码中的“ Blah Blah Blah”),则可能会遇到-但我想并非如此。

正如问题的标题是“将startForeground()与IntentService一起使用”一样,我也想澄清一下:我相信没有什么(架构,最佳实践,android框架,IntentService的Java文档)会阻止您将Intent服务作为前台运行。当然,您需要仔细考虑其用法以及您是否确实需要前台服务。这里有一些想法。有关示例代码,请参见下文。(如果您将多个作业/意图排队到IntentService中,则示例代码最终可能会显示多个通知,因此根据您的需要,可能会有更好的解决方案。)


public class ForegroundService extends IntentService {

    private static final String TAG = "FrgrndSrv";

    public ForegroundService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        Notification.Builder builder = new Notification.Builder(getBaseContext())
                .setSmallIcon(R.drawable.ic_foreground_service)
                .setTicker("Your Ticker") // use something from something from R.string
                .setContentTitle("Your content title") // use something from something from
                .setContentText("Your content text") // use something from something from
                .setProgress(0, 0, true); // display indeterminate progress

        startForeground(1, builder.build());
        try {
            doIntesiveWork();
        } finally {
            stopForeground(true);
        }
    }

    protected void doIntesiveWork() {
        // Below should be your logic that takes lots of time
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @CommonsWare我明白你的意思了。那讲得通。实际上,我对您所说的“通常寿命不超过几秒钟”的说法完全不同意。我并不是在做假设,而是只是阅读Java文档,而Java文档没有诸如“通常不应生存几秒钟”之类的假设。 (3认同)

Jox*_*aex 0

如果内存不足并且您消耗了太多内存并且您在后台运行的时间太长,那么您将被 ActivityManager 杀死。