当活动关闭时服务停止运行。

5
我已经阅读了很多关于这个问题的答案,它们似乎都是相同的:
“使用START_STICKY运行您的服务”
“在前台运行您的服务”
“使用startService而不绑定它来运行您的服务”
我正在做所有这些事情,但我的服务仍然在每次关闭我的活动时关闭并重新启动。
这不是IntentService。
我也没有在任何地方调用stopSelf或stopService,除了在onClick处理程序中。
请向下滚动到我的更新 - 这种行为已经被确认是Android操作系统中的一个错误,并且我已经向Google报告了此问题。单击此处查看报告。
从MainActivity启动我的服务:
svcIntent = new Intent(getBaseContext(), MyService.class);
startService(svcIntent);

在我的 onStartCommand 方法中:
        // Enter foreground state
    String title = "Service has been started...";
    String subject = "Service is running...";
    String body = "Monitoring your battery usage.";
    Notification notification = new Notification(R.drawable.theicon, title,
            System.currentTimeMillis());
    if (prefs.getBoolean("notificationSounds", true))
        notification.defaults |= Notification.DEFAULT_SOUND;
    else
        notification.sound = null;
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(this, subject, body, pendIntent);
    startForeground(1500, notification);

在我的onStartCommand结尾处:
...
// Release WakeLock
wl.release();

    return START_STICKY;

更新

我找到了问题的原因!但是我不知道该如何修复它。在我的服务中,我还使用了AlarmManager,在服务内部设置函数调用,在指定的时间后执行。

        // Alarm manager setup for MyService
    AlarmManager AM = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    svcIntent1 = new Intent(this, AlarmReceiver.class);
    prefs.edit().putInt("initialBatt", initialBatt).apply();
    svcIntent1.setAction("com.myApp.servicealarm");
    pendingIntent = PendingIntent.getBroadcast(this, 93, svcIntent1, PendingIntent.FLAG_UPDATE_CURRENT);

    // Set the alarm
    AM.set(AlarmManager.RTC_WAKEUP, timeNow + waitTime, pendingIntent);

我注意到,如果我不注释AM.set调用以设置闹钟,即使onReceive为空,当闹钟响起时,我的服务也会在我在最近的应用程序中滑动后被终止。如果我注释掉设置闹钟的调用,则服务永远不会被杀死,并在我关闭应用后继续运行。这是怎么回事?!我需要这个闹钟来实现我的算法功能!!
非常奇怪。一旦闹钟响起,我的调试消息就不打印了,我的服务重新启动。但第二次,服务重新启动后,调试消息确实打印出来,程序成功执行。
我已经尝试过使用普通广播接收器,情况仍然如此。我还将代码剥离为仅包含来自我的服务和广播接收器的设置闹钟调用,结果仍然相同,因此不是我的算法。显然,如果您有一个设置闹钟的前台服务,当闹钟响起时,您的服务将重新启动。

这种行为似乎是由安卓操作系统的一个错误引起的,所以我不指望得到答案。如果您想亲自查看此错误,请 点击此处。我提供了一个项目,您可以编译并重现此问题。


"我的服务每次活动关闭时仍然会关闭并重新启动" -- 您是如何确定这一点的?您是否在任何地方调用了 stopService()stopSelf()?这是一个 IntentService 吗? - CommonsWare
你是如何关闭你的应用程序的? - iheanyi
@pskink 我会覆盖它并检查。 - JayB
1
已报告。https://code.google.com/p/android/issues/detail?id=104308 - JayB
@nida 将意图作为前台意图发送。请参见已接受的答案。 - JayB
显示剩余16条评论
2个回答

4

在发送广播Intent之后(在您的应用程序中接收/处理之前),Android会杀死进程。这是一个令人讨厌的Android漏洞,从4.4(API 19)开始存在。

请参见https://code.google.com/p/android/issues/detail?id=63618&can=1&q=service%20restart%20broadcast&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars,特别是评论#22和#23。

不幸的是,最近几乎所有“开放”的问题都被标记为“已过时”,假设它们在Android 5.0中都得到了修复。开发人员无法重新打开“已过时”的问题。


编辑:添加有关前台广播的详细信息

根据链接问题中的信息,似乎将Intent.FLAG_RECEIVER_FOREGROUND添加到广播Intent中将确保下一次接收广播Intent时,进程不会被杀死。

要执行此操作,请添加:

svcIntent1.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

AlarmManager中设置闹钟的代码中,您需要进行翻译。

请阅读链接问题中的评论以获取更多细节。


看到这个,我觉得很奇怪!我知道这一定是一个bug,它根本没有意义。谢谢提供链接。看来我得加入一个虚假的消息“正在后台模式下启动”哈哈。 - JayB
请告诉我这是否解决了你的问题。 - David Wasser
1
@JayB:如评论#23所述,您可以使用前台“Intent”作为广播来解决此问题。@David,您可能希望将此添加到您的答案中。 - corsair992

0
尝试在单独的进程中运行您的服务。在清单文件中像这样定义它:
<service
   android:name=".path.to.service.class"
   android:process=":my_service"/>

刚试了一下,当我在最近使用的应用程序中滑动关闭我的应用程序时,它仍然会关闭。 - JayB
我找出了问题的原因,请看我的更新,但我不知道如何阻止它再次发生。 - JayB

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