调试服务崩溃问题

6
我有一个音乐服务,负责在后台进行音乐播放,还有一些其他的功能,例如通知UI更改所需的活动,存储和恢复队列,通过光标获取歌曲记录,每次歌曲更改时,它会更新正在进行的通知上的位图。问题是什么?当用户尝试做其他事情时,服务几乎总是崩溃。例如,播放歌曲,然后打开游戏会导致服务崩溃,有时像使用Chrome浏览网页这样的轻量级操作也会导致崩溃。一些细节:1-服务是通过startService(new Intent(this,MyMusicService.class))启动的,但当用户离开活动时,我调用startForeground(mId,mNotification)来显示一个持续的通知,提供易于控制的选项,也因为startForeground()适用于应优先考虑的服务,如果activityManager杀死这些服务,将会影响用户体验(停止播放音乐)。

2 - 我已经尝试复制这个崩溃,它通常发生在进行轻度工作时,例如使用chrome浏览器(这将几乎50%的时间复制崩溃),并且总是在启动temple run 2等操作时发生。如果什么都不做 - 只是在后台播放音乐和空闲,回放不会停止,而是按照预期的方式工作。

3 - 我用作测试设备的手机绝不是慢速或低内存设备,它是Galaxy Nexus。

4 - 我已经尝试捕获了一些长整型数据,有时它只是说:

02-24 06:53:32.586: I/ActivityManager(387): Process com.deadpixels.light.player (pid 27720) has died.

没有其他消息,有时相同的消息会伴随着WINDEATH:。
 02-24 06:53:32.586: W/ActivityManager(387): Scheduling restart of crashed service com.deadpixels.light.player/.service.MyMusicService in 5000ms
 02-24 06:53:32.602: W/InputDispatcher(387): channel '418d09c8    com.deadpixels.light.player/com.deadpixels.light.player.HomeActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
 02-24 06:53:32.602: E/InputDispatcher(387): channel '418d09c8 com.deadpixels.light.player/com.deadpixels.light.player.HomeActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
 02-24 06:53:32.602: W/InputDispatcher(387): Attempted to unregister already unregistered input channel '418d09c8 com.deadpixels.light.player/com.deadpixels.light.player.HomeActivity (server)'
 02-24 06:53:32.602: I/WindowState(387): WIN DEATH: Window{418d09c8 u0 com.deadpixels.light.player/com.deadpixels.light.player.HomeActivity}

我注意到的另一个问题是,几乎每次崩溃发生时,许多其他服务都会“死亡”。我在此附上完整日志here5 - 我尝试使用ACRA获取有关崩溃的更多信息,但即使一切似乎设置正确,在崩溃后日志也没有被发送,或者什么也没有发生。我知道ACRA检测到崩溃并启动了:
02-24 06:53:37.719: D/ACRA(28293): ACRA is enabled for com.deadpixels.light.player, intializing...
02-24 06:53:37.742: D/ACRA(28293): Using default Mail Report Fields
02-24 06:53:37.742: D/ACRA(28293): Looking for error files in /data/data/com.deadpixels.light.player/files
02-24 06:53:37.742: W/ACRA(28293): com.deadpixels.light.player reports will be sent by email (if accepted by user).

但是没有任何东西被发送,既不发送到我设置的mailto,也不发送到Google文档中的表单。

不确定还有什么其他尝试方法,希望能得到一些好的想法来寻找解决方法。正如我所说,该服务确实会做一些事情,据我所知,这些事情并不需要太多资源,老实说,我甚至不确定它是否与服务崩溃有关。

这里是gist的几个代码片段和我设置的ACRA代码。值得注意的是,我尝试使用其他音乐播放器重现服务崩溃,并且根本没有遇到任何问题。

感谢您的帮助!

4个回答

3
似乎操作系统认为你的服务在用户离开你的活动后就进入了后台,尽管它是一个“前台”服务。
我会设计您的MyMusicService服务有所不同:
  1. onCreate中准备MediaPlayer
  2. 在您的服务的onStartonStartCommand实现中,开始播放选定/适当的声音文件。如果希望即使设备处于睡眠状态也能继续播放音乐,请获取部分唤醒锁。返回START_STICKY
  3. 将通知添加到状态栏。 3 在onDestroy中,清理一切。
当音乐停止时,无论是用户交互还是歌曲结束,请确保删除通知并释放唤醒锁。
这里可以找到一个不错的教程。 http://www.youtube.com/watch?v=mcb99u8Nlgs&list=PL14AA2548E3C96B50

在OP添加评论/更新“gist”后更新:

我看到你的服务中的BroadcastReceiver mReceiveronReceive访问了一个数据库。这可能是问题所在。将其转移到IntentService中:在onReceive中,只需使用与onReceive接收到的相同Intent启动一个IntentService。然后IntentService可以执行所有实际工作,而不必担心任何可能导致进程终止的缓慢数据库访问。

如果在设备睡眠时仍需要播放音乐,请确保获取部分唤醒锁(并在必要时释放它!)。


我已经在onStartCommand中返回了START_STICKY。至于onCreate,我确实初始化了播放器,但是我不能调用prepare,因为服务甚至在请求播放音乐之前就已经启动了,因此我不知道应该传递哪首歌曲的路径。此外,当一首歌曲正在播放时,我会添加状态栏通知,我不确定你是否看过我发布的要点。然而,我将研究获取唤醒锁,因为我认为我不需要它,因为即使我没有使用手机,它也可以在后台播放30分钟的音乐。 - daniel_c05
在“gist”链接中,我没有看到任何“onStart”或“onStartCommand”的实现,所以我才问的:) 如果您在服务的onCreate中调用“startForeground”,则部分唤醒锁仅在您希望即使设备处于睡眠状态时也要播放时才有用。“startForeground”应该已经防止了设备不处于睡眠状态时杀死服务。您是否检查了服务广播接收器中onReceive方法的实现?它们必须快速运行;如果不是,则可能会杀死您的进程。 - Streets Of Boston
嗨,你说得对,我没有包括onStartCommand,我现在已经添加了,因为我更新了gist。此外,我只在离开活动时调用startForeground(即当转到主页或另一个活动时),并在恢复时调用stopForeground(true)。至于onReceive,我不确定如何测试它是否运行快速。我在gist中添加了一些onReceive的代码片段。 - daniel_c05
如果在onReceive中进行任何数据库/文件/存储/网络访问,它有可能运行得太慢。 - Streets Of Boston
我一直保存这些更改,以防你想要查看。理论上,在调用播放新歌曲时,我会在onReceive期间进行数据库访问。不确定是否还有其他潜在的更改方式。后台线程(即AsyncTask)? - daniel_c05
你知道这句话的意思吗:"消费者关闭了输入通道或发生错误。事件=0x9"? - daniel_c05

2
我遇到了同样的问题,你可以检查一下你的mId是否和通知的id相同?还要确保它不等于0,因为如果等于0,它将与活动的id相关联并随着活动的结束而结束。
另外,请检查你的代码是否使用onStartCommand而不是onHandle。

0
请检查您的代码,也许在某个地方您自己销毁了进程,例如 System.exit(0);,如果您这样做,那么就会有日志记录。
channel '418d09c8    

com.deadpixels.light.player/com.deadpixels.light.player.HomeActivity(server)'
 ~ Consumer closed input channel or an error occurred.  events=0x902-24 06:53:32.602:
 E/InputDispatcher(387): channel '418d09c8 
 com.deadpixels.light.player/com.deadpixels.light.player.HomeActivity (server)'
  ~ Channel is unrecoverably broken and will be disposed!

0

如果您提供有关您的架构的更多信息,特别是您的Activity和Service如何交互,那肯定会有所帮助。

当然,这只是猜测,但对我来说,听起来好像您的Service引用了您的Activity。一旦您使用其他应用程序,您的Activity很可能会被销毁。

几个问题。

  • 您的服务和Activity是否在同一个进程中运行?(这会影响Activity和Service之间可以共享的信息。)
  • 您的Activity类是否有任何变量,Service尝试访问它们?(如果有的话,它们应该属于Application类。)

是的,它们都在同一个进程上运行。我尝试过使用不同的进程,但是aidl接口让我感到非常困扰。至于访问,它们大多通过意图进行通信,比如用户在活动中点击播放按钮,然后会发送一个广播,服务会捕获并播放广播中指定的歌曲。回答你的第一个问题,服务没有保留对活动的引用。 - daniel_c05

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