Create notification early for headset events

Headset events are the only place where we are forced to use the startForegroundService call which requires us to call startForeground() within 5 sec.

This will *usually* work fine, but fails if the device somehow failes to be fast enough OR if there is no song available.
Having an option to create a notification in onStart() in any case avoids the ANR crash in such strange cases.
This commit is contained in:
Adrian Ulrich 2017-09-17 13:57:31 +02:00
parent 2f80739804
commit b62cc51689
2 changed files with 16 additions and 11 deletions

View File

@ -186,15 +186,11 @@ public class MediaButtonReceiver extends BroadcastReceiver {
if (act == null)
return;
Intent intent = new Intent(context, PlaybackService.class).setAction(act);
Intent intent = new Intent(context, PlaybackService.class)
.setAction(act)
.putExtra(PlaybackService.EXTRA_EARLY_NOTIFICATION, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Since API 26, we can not use startService anymore if the service
// was not launched. startForegroundService() expects the service
// to call startForeground() within 5 sec, which is PROBABLY okay as
// any key event will start playing a song - probably.
// If this fails, we could still try the chromium hack and have
// PlaybackService:onCreate() start a fake notification.
// https://chromium.googlesource.com/chromium/src/+/81033db0364139db8ee059623d8892f2b00a39ba
context.startForegroundService(intent);
} else {
context.startService(intent);

View File

@ -177,6 +177,10 @@ public final class PlaybackService extends Service
* Pause music and hide the notifcation.
*/
public static final String ACTION_CLOSE_NOTIFICATION = "ch.blinkenlights.android.vanilla.CLOSE_NOTIFICATION";
/**
* Whether we should create a foreground notification as early as possible.
*/
public static final String EXTRA_EARLY_NOTIFICATION = "extra_early_notification";
/**
* Visibility modes of the notification.
@ -515,10 +519,15 @@ public final class PlaybackService extends Service
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
final String action = intent.getAction();
final boolean earlyNotification = intent.hasExtra(EXTRA_EARLY_NOTIFICATION);
if (earlyNotification) {
Song song = mCurrentSong != null ? mCurrentSong : new Song(-1);
startForeground(NOTIFICATION_ID, createNotification(song, mState, VISIBILITY_WHEN_PLAYING));
}
if (ACTION_TOGGLE_PLAYBACK.equals(action)) {
playPause();