MediaPlayer在单独的线程中与在服务中通过startForeground()运行

时间:2012-01-18 18:48:30

标签: android

所以,我在一个单独的线程中播放音乐。如果我离开应用程序(onPause()onStop()被调用等),音乐将继续播放,但最终 - 在打开其他应用并在它们之间切换并返回主屏幕之后 - 我的应用程序被杀了。没有崩溃,只有logcat中的WIN DEATHprocess com.myapp.android has died。显然,系统为了回收资源而销毁应用程序是合法的。

我的问题是:在主(UI)线程的线程中运行东西是否意味着它现在具有较低的优先级,就系统而言?这意味着,与在Service中运行媒体播放器甚至使用startForeground()使服务在前台运行相比,它是否更容易被杀死?

非常感谢任何想法或澄清!

修改

此外,有关服务的部分文件让我感到困惑。在相关部分,它指出:

  

警告:服务在其托管进程的主线程中运行 -   service不会创建自己的线程,也不会在a中运行   单独的过程(除非你另有说明)。这意味着,如果   您的服务将进行任何CPU密集型工作或阻止   操作(如MP3播放或网络),你应该创建一个   服务中的新线程来完成这项工作。

我总是在主线程的服务中运行MP3播放,并且UI保持响应。如果我应该把它放在上面引文中推荐的一个单独的线程中,那么我最终不会回到我开始的地方,即在主线程中发生媒体播放,从而增加了回放的可能性打开其他应用程序时会被杀死吗?

3 个答案:

答案 0 :(得分:7)

我刚刚在其他地方发布了部分答案,但它仍然相关。

不幸的是,调用prepareAsync()根本不足以避免ANR提示和应用程序挂起几秒钟,特别是如果您正在从网络播放文件。最好的办法是将MediaPlayer实例放在自己的线程中,或者至少在Handler中执行密集调用(如mediaplayer.start())。我已经使用MediaPlayer超过一年了,我可以告诉你它肯定会在各种电话后挂起,具体取决于具体情况。

理想情况下,您应该从服务中生成一个控制MediaPlayer的线程。这样,您可以确保在应用程序处于后台时继续播放媒体,任何阻止调用(除了prepare()/ prepareAsync())都不会挂起您的应用。

答案 1 :(得分:2)

我认为您的大部分问题都在Android documentation on Services中得到了解答。

从链接:

  

前台服务是一种被认为是某种东西的服务   用户积极地意识到并因此不是系统的候选者   在内存不足时杀死。前台服务必须提供   状态栏的通知,位于“正在进行”下   标题,这意味着除非通知不能被驳回   该服务要么停止要么从前台删除。

要回答您的问题,是的,从Thread单独运行Activity的优先级低于在前台运行的Service如果{启动Activity的{​​1}}已停止/暂停。

就个人而言,我建议在Thread中执行此操作,因为这正是Service类的创建方式。

修改

有趣的是,你的建议似乎与我所读到的相反(在Service中不使用线程时,一切都是响应的)。无论如何,它可能应该在后台线程中启动。

线程(您创建的线程)将不会死,除非进程终止,并且当运行时决定需要资源时将发生这种情况。当Service不在前台时可以被杀死,所以他们的Activity也可以被摧毁。如果您将Thread标记为前景,则不太可能被销毁,因此,您不应该遇到同样的问题。

答案 2 :(得分:-1)

无需从线程运行MediaPlayer。只要您使用MediaPlayer.prepareAsync而不是MediaPlayer.prepare,MediaPlayer上就没有任何方法会阻塞足够长的时间来导致问题。在服务的前台线程上运行它。

如果你的进程被杀死,那么线程就会随之而来。如果您调用Service.startForeground方法(并在状态栏上显示由startForeground需要的强制通知),则托管服务的进程的寿命比活动长。一旦活动暂停,整个过程就成为回收的主要候选者(假设此过程中没有前台服务)。