我已经阅读了有关Android M中新的'Doze'模式的几篇文章,以及Android Developers网站上的文章:https://developer..android.com/training/monitoring/monitoring-device-device-device-State/doze-standby.html,但我仍然有一个问题,即在手机上正确运行前景服务(Android 6.0.1)。
问题:
我有一项服务,可以使用MediaPlayer对象处理音乐,该服务实现onCompletion
和onPrepared
MediaPlayer Interfaces。
伪代码:
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分钟之间)时,一旦调用了一旦调用,服务就无法检索下一个曲目。
服务已设置并符合以下条件:
- 服务通知始于
startForeground
- MediaPlayer对象具有部分Wakelock
PARTIAL_WAKE_LOCK
- 该服务在主应用程序/UI 的单独过程中运行
- 所有媒体使用
prepareAsync()
(逻辑获得下一个曲目URI是在背景线程中执行的,PrepareAsync()仅在主线程中调用)
)
我尝试过的东西:
- 在主线程中检索下一首歌(在启动之后调用),而不是背景线程
- 在OnCompletion()中获取单独的部分Wakelock,然后在OnPrepared()时持有然后将其释放。
- 其他几个无济于事的琐碎事物...
我有一个logcat输出,从保留手机时,屏幕关闭了一段时间,然后将其插入屏幕,然后将其插入(一旦我将其插入并更新日志),就可以获得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()
- 准备好称呼 - 开始播放和更新通知使用Start Foreground
从日志中您可以在02:38:59.xxx oncompletion中看到,找到了一个轨道,然后返回到调用prepareasync()的主线程,但随后没有发生12分钟的时间,直到我手动手动唤醒打电话给电话,此时只有代码继续停止并开始播放轨道。
我不认为它是我在这种情况下使用正常工作的其他音乐应用程序的设备,但是我仅限于在一个真实设备上进行测试:(
如果您对与我的关系非常感谢!任何建议都将不胜感激(希望关于解决方案,而不是我的音乐品味!)
我只是想让您看到我如何实现我的startForeground()
方法。也许这可以有所帮助:
void setUpAsForeground(String text) {
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Main.class), 0);
NotificationCompat.Builder noti = new NotificationCompat.Builder(this)
.setContentTitle( "My App Title")
.setContentText(text)
.setSmallIcon(R.drawable.ic_stat_recording)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(text))
.setPriority(Notification.PRIORITY_MAX)
.setContentIntent(contentIntent)
.setOngoing(false);
final Notification notification = noti.build();
//mNotificationManager.notify(NOTIFICATION_ID, noti.build());
startForeground(NOTIFICATION_ID, notification);
}
和onCreate()
:
@Override
public void onCreate() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
***********
}