我已经阅读了几篇有关Android M中新的“打ze”模式的文章,以及Android开发者网站上的文章:https://developer.android.com/training/monitoring-device-state/doze-standby.html,但是我仍然无法正确在手机(Android 6.0.1)上运行Foreground Service。

问题:

我有一个使用MediaPlayer对象处理播放音乐的服务,该服务实现了onCompletiononPrepared MediaPlayer接口(interface)。

伪代码:

    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
  • 服务在与主应用程序/UI分开的过程中运行
  • 所有媒体都使用prepareAsync()(逻辑以获取下一个轨道uri在后台线程中执行,prepareAsync()仅在主线程中调用)

  • 我尝试过的事情:
  • 检索主线程中的下一首歌(在onCompletion之后),而不是背景线程
  • 在onCompletion()中获取一个单独的Partial 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()称为
  • 获取唤醒锁下一曲
  • PrepareAsync()
  • onPrepared调用-使用startForeground
  • 开始播放并更新通知

    从02:38:59.xxx的日志中可以看到,调用了onCompletion的onCompletion,找到了一条轨道,并返回到调用了prepareAsync()的主线程,但是在12分钟内没有任何 react ,直到我手动唤醒电话,并在该点继续执行代码,然后在停止的位置继续播放轨道。

    在这种情况下,我认为它的设备不如我使用的其他音乐应用程序正常,但是我仅限于在一台真实设备上进行测试:(

    如果您已经走了这么远,多谢您与我联系!任何建议将不胜感激(希望有关解决方案,而不是我的音乐品味!)。

    最佳答案

    我只是想让您看看我如何实现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();
    
        ***********
    }
    

    09-11 19:35