【发布时间】:2016-06-15 11:29:56
【问题描述】:
我已经阅读了几篇关于 Android M 中新的“打盹”模式的文章,以及 Android 开发者网站上的文章:https://developer.android.com/training/monitoring-device-state/doze-standby.html 但我仍然遇到在手机上正确运行前台服务的问题(Android 6.0.1 )。
问题:
我有一个使用 MediaPlayer 对象处理播放音乐的服务,该服务实现 onCompletion 和 onPrepared MediaPlayer 接口。
伪代码:
public class MusicService extends Service implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
// Class Variables/Methods etc...
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
// update notification using startForeground()
}
@Override
public void onCompletion(MediaPlayer mp) {
// Go and get another music track in separate thread
// (Have used AsyncTask and RX Java/RX Android to test if problem is here - works fine)
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// handleError
return false;
}
}
当手机插入电源时,或者屏幕打开时,或者应用程序打开并且屏幕打开时,该应用程序运行良好。但是,当手机处于空闲状态并播放音乐(5 到 40 分钟之间)时,一旦调用 onCompletion(),服务将无法检索下一首曲目。
服务已设置并满足以下条件:
- 服务通知以
startForeground开始 - MediaPlayer 对象具有部分唤醒锁
PARTIAL_WAKE_LOCK - Service 在主应用程序/UI 的单独进程中运行
- 所有媒体使用
prepareAsync()(获取下一曲目uri的逻辑在后台线程中执行,仅在主线程中调用prepareAsync())
我尝试过的事情:
- 在主线程而不是后台线程中检索下一首歌曲(在调用 onCompletion 之后)
- 在 onCompletion() 中获取单独的 Partial WakeLock,并在调用 onPrepared() 时保持并释放它。
- 几乎没有其他无关紧要的小事...
我有一个 logcat 输出,从手机离开时开始,在屏幕关闭的情况下一段时间未触摸,并且 UNPLUGGED(logcat 在我重新插入并更新日志后获得),这表明了问题。
06-15 02:31:39.346 musicplayer:music_service E/MusicService: onPrepared : Tom Petty GH - 11 - You Got Lucky
06-15 02:31:39.548 musicplayer:music_service D/MusicService: Releasing wakelock
06-15 02:35:15.467 musicplayer:music_service E/MusicService: onCompletion called
06-15 02:35:15.467 musicplayer:music_service D/MusicService: Acquiring wakelock
06-15 02:35:15.514 musicplayer:music_service D/NextActionStrategy: Retrieving song - rx java - Main Ui Thread =false
06-15 02:35:15.870 musicplayer:music_service D/NextActionStrategy: Song Retrieved : Ten Years- Main Ui Thread = true
06-15 02:35:15.950 musicplayer:music_service E/MusicService: onPrepared : Ten Years
06-15 02:35:16.149 musicplayer:music_service D/MusicService: Releasing wakelock
06-15 02:38:59.002 musicplayer:music_service E/MusicService: onCompletion called
06-15 02:38:59.002 musicplayer:music_service D/MusicService: Acquiring wakelock
06-15 02:38:59.049 musicplayer:music_service D/NextActionStrategy: Retrieving song - rx java - Main Ui Thread =false
06-15 02:38:59.211 musicplayer:music_service D/NextActionStrategy: Song Retrieved : What Am I- Main Ui Thread = true
06-15 02:50:07.642 musicplayer:music_service E/MusicService: onPrepared : What Am I
06-15 02:50:07.976 musicplayer:music_service D/MusicService: Releasing wakelock
06-15 02:50:22.097 musicplayer:music_service D/MusicService: onStartCommand called : action.PAUSE
例程是
- 播放曲目
- onCompletion() 调用
- aquire wakelock 获取下一首曲目
- PrepareAsync()
- onPrepared 调用 - 使用 startForeground 开始播放和更新通知
从日志中你可以看到 02:38:59.xxx onCompletion 被调用,找到了一个轨道,并返回到调用 prepareAsync() 的主线程,但是在我手动唤醒之前 12 分钟没有任何反应打电话,然后代码继续在哪里停止并开始播放。
我认为它的设备不像我使用的其他音乐应用程序在这种情况下可以正常工作,但是我仅限于在一台真实设备上进行测试:(
如果你已经走到这一步,感谢你对我的包容!任何建议都将不胜感激(希望是关于解决方案而不是我的音乐品味!)。
【问题讨论】:
-
您是否已将您的应用列入白名单?您必须在设置中手动执行此操作。并且请注意华为设备,他们在打盹模式旁边还有另一个省电管理。在这里你必须同时处理这两个......
-
@Opiatefuchs - 这是我与其他媒体播放器应用程序无关的事情 - 这是唯一的方法吗?
-
伙计,我在这方面挣扎了很久。我有一个带棒棒糖的华为 Ascend Mate 7。一切都很好,因为我知道电池保护程序以及如何处理它。然后,更新来了 MM,没有任何效果。原来这是华为的一个bug,后来他们更新了MM,然后就成功了。那么,你的设备和安卓版本是什么?另外,我看到了一个奇怪的事情,像 WhatsApp 这样的一些应用程序在设置中具有其他人没有的特殊功能,所以它必须是供应商的实现,没有开发人员可以处理它。
-
现在,它不关心它是哪种应用程序,在 MM 你必须将它列入白名单。这只能通过用户交互来实现。我将通过 API 建议的意图完成它,但是如果他们认为没有必要,谷歌可能会从 Playstore 中踢出你的应用程序。无论如何,我已经实现了一个 AlarmManager,它通过部分唤醒锁每 x 分钟唤醒一次。
-
不,以 API22 为目标无法解决该问题。然后,由于没有可用的方法,您将无法让警报管理器执行。您应该尝试使用警报管理器,因为它在文档中指出唤醒锁被忽略。而是使用来自 alarmManager 的方法
setAndAllowWhileIdle()或setExactAndAllowWhileIdle()。setAlarmClock也可以工作,但是您在设备顶部有一个时钟图标,并且可以通过系统时钟看到警报。
标签: java android android-mediaplayer