Android服务播放音乐:为什么使用START_STICKY?

3

我正在开发一款用于播放音乐的安卓应用。

目前,我从负责播放音乐的服务的onStartCommand方法中返回了START_STICKY,但并没有考虑太多。因为在Eclipse的提示工具中指出:“对于执行后台音乐播放的服务,此模式是有意义的”。

该方法的第一件事是查看意图(play、stop、下一首歌曲等)。

最近,当我在播放音乐时关闭应用程序(通过在最近使用的应用程序概览中将其拖出屏幕)时,应用程序崩溃了。查看日志文件后,我发现在调用应用程序和服务的onCreate方法之后,在onStartCommand中访问意向时抛出了空指针异常。

因此,我的第一反应是在onStartCommand方法的开头插入以下代码:

if (intent == null){
    stopSelf();
    return START_NOT_STICKY;
}

但是我再次阅读START_STICKYSTART_NOT_STICKY的描述后,我想知道:为什么会建议音乐播放器使用START_STICKY
我的理解是,两者之间的区别在于,如果使用START_STICKY启动的服务被杀死,它将重新启动(然后带有intent=null)。使用START_NOT_STICKY时,除非用户请求,否则该服务将不会重新启动,因此它将始终被调用,并且我不需要检查它是否为null。
当用户关闭应用程序时,我认为服务不应该重新启动。
我能想到的另一种情况是,如果由于资源不足而导致系统杀死了服务。即使某些资源变得可用,用户也不希望出现意外开始播放音乐的情况。
以下两个答案暗示返回代码除了确定服务是否应该在进程被杀死后重新启动之外,没有其他含义: 为什么建议音乐播放器使用START_STICKY

播放音乐不需要新的服务。当您使用mediaPlayer类时,已经创建了一个服务。 - Sharath kumar
即使在其他应用程序位于前台时,音乐也应该持续在后台播放,@匿名。 - jakun
默认情况下,它将在后台运行。只有当用户从内存中清除最近使用的应用程序时,音乐才会停止。例如像 Spotify。 - Sharath kumar
我尝试了@Anonymous提到的MediaPlayer。然而,我认为这不是作者所要求的。Jakun的问题是为什么START_STICKY对于音乐播放有意义。根据文档,服务将使用空intent重新创建。因此,这意味着如果我们通过intent在服务中指定要播放的音乐,则在重新创建后服务将无法工作,因为我们无法使用空intent获取要播放的音乐,并且即使播放固定的mp3,它也将从0'00''开始,而不是用户从最近使用的应用程序中清除时停止的位置。所以我也有同样的问题。 - LiuWenbin_NO.
2个回答

1

START_STICKY- 如果由于内存不足而停止服务,则在恢复内存后,会重新创建该服务。在此期间,您可能会丢失之前计算的结果。

START_NOT_STICKY- 如果停止服务,则系统不会打扰重启服务,即使它有足够的内存。

另外,当用户关闭应用程序时,除非使用某些任务杀手停止进程,否则服务将不会停止。有关服务的更多信息,请查看此链接。

http://www.vogella.com/tutorials/AndroidServices/article.html


关于START_STICKYSTART_NOT_STICKY的含义:这看起来与我在提到的答案中看到的非常相似。我相信理解两者之间的区别。我的问题是:为什么对于音乐播放器,推荐使用START_STICKY - jakun
好的,说到音乐播放器创建服务的优点,这里有一个:当音乐播放器应用程序被杀死,而你已经创建了正在播放的歌曲,它将不会停止。使用START_STICKY将确保如果服务被Android系统杀死以获得内存,则重新开始播放歌曲,但是从头开始,而START_NOT_STICKY将不会重新启动服务,除非您手动进入应用程序并播放歌曲。 - Sharath kumar
关于关闭应用程序的问题:我使用了滑动手势将其从最近应用程序列表中移除,该列表在长按主屏幕按钮时打开。这样做后,音乐立即停止播放,这对我来说是明确的服务已经停止的迹象。应用程序崩溃是在我返回主屏幕后发生的。 - jakun
是的,这就是我说的。媒体播放器有一个服务,可以让你在最小化应用程序并转到其他应用程序时听歌。但是,如果你清除了应用程序,它会被终止。如果你在Play商店中检查任何样本音乐应用程序,大多数都已经实现了这种机制。 - Sharath kumar
你说的“它不会停止”是START_STICKY和START_NOT_STICKY之间的另一个区别吗?你指的是哪种情况(用户杀死应用程序还是操作系统杀死应用程序 - 是否有区别)? - jakun
显示剩余4条评论

0
int START_STICKY: 这是一个常量,可从onStartCommand(Intent, int, int)返回。如果此服务的进程在启动后被杀死(从onStartCommand(Intent, int, int)返回后),则将其保留在已启动状态,但不保留此传递的意图。稍后系统将尝试重新创建服务。因为它处于已启动状态,所以在创建新的服务实例后,它将保证调用onStartCommand(Intent, int, int);如果没有任何待处理的启动命令要传递到服务,则将使用空意图对象调用该方法,因此您必须注意检查此情况。此模式对于需要明确启动和停止以运行任意时间段的事物非常有意义,例如执行后台音乐播放的服务。 因此,它是自我解释的,请参考STICKY SERVICE

这句话的意思是,“如果该服务的进程被杀死,让它保持启动状态”?听起来像是该服务应该继续运行,但事实并非如此。当我关闭应用程序时,音乐会停止(立即停止,在应用程序崩溃之前)。 - jakun
@jakun 可能你在清单文件中将 Stopwithtask 属性设置为 true,这就是为什么当你杀死应用程序时服务会停止。它不会突然自动开始播放,你有控制权来停止服务。 - Hardik Mehta
不,我在清单文件中只设置了两个属性:android:name和android:enabled="true"。没有Stopwithtask。 - jakun
当服务重新启动时,我可以按照我的问题描述停止服务。但是,为什么我要告诉Android首先应该重新启动服务呢? - jakun
@jakun,我们并不是在告诉Android重新启动服务,而是START_STICKY会导致服务在启动状态后被杀死时重新启动。 - Hardik Mehta
显示剩余3条评论

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