Skip to content

Commit b764ad3

Browse files
committed
Drop some assumptions on how PlayerService is started and reused
Read the comments in the lines changed to understand more
1 parent c6e1721 commit b764ad3

4 files changed

Lines changed: 43 additions & 21 deletions

File tree

app/src/main/java/org/schabi/newpipe/ktx/Bundle.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,16 @@ import androidx.core.os.BundleCompat
77
inline fun <reified T : Parcelable> Bundle.parcelableArrayList(key: String?): ArrayList<T>? {
88
return BundleCompat.getParcelableArrayList(this, key, T::class.java)
99
}
10+
11+
fun Bundle?.toDebugString(): String {
12+
if (this == null) {
13+
return "null"
14+
}
15+
val string = StringBuilder("Bundle{")
16+
for (key in this.keySet()) {
17+
@Suppress("DEPRECATION") // we want this[key] to return items of any type
18+
string.append(" ").append(key).append(" => ").append(this[key]).append(";")
19+
}
20+
string.append(" }")
21+
return string.toString()
22+
}

app/src/main/java/org/schabi/newpipe/player/PlayerService.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import android.os.IBinder;
2929
import android.util.Log;
3030

31+
import org.schabi.newpipe.ktx.BundleKt;
3132
import org.schabi.newpipe.player.mediasession.MediaSessionPlayerUi;
3233
import org.schabi.newpipe.player.notification.NotificationPlayerUi;
3334
import org.schabi.newpipe.util.ThemeHelper;
@@ -41,6 +42,7 @@
4142
public final class PlayerService extends Service {
4243
private static final String TAG = PlayerService.class.getSimpleName();
4344
private static final boolean DEBUG = Player.DEBUG;
45+
public static final String SHOULD_START_FOREGROUND_EXTRA = "should_start_foreground_extra";
4446

4547
private Player player;
4648

@@ -59,35 +61,39 @@ public void onCreate() {
5961
assureCorrectAppLanguage(this);
6062
ThemeHelper.setTheme(this);
6163

62-
player = new Player(this);
63-
/*
64-
Create the player notification and start immediately the service in foreground,
65-
otherwise if nothing is played or initializing the player and its components (especially
66-
loading stream metadata) takes a lot of time, the app would crash on Android 8+ as the
67-
service would never be put in the foreground while we said to the system we would do so
68-
*/
69-
player.UIs().get(NotificationPlayerUi.class)
70-
.ifPresent(NotificationPlayerUi::createNotificationAndStartForeground);
64+
// Note: you might be tempted to create the player instance and call startForeground here,
65+
// but be aware that the Android system might start the service just to perform media
66+
// queries. In those cases creating a player instance is a waste of resources, and calling
67+
// startForeground means creating a useless empty notification. In case it's really needed
68+
// the player instance can be created here, but startForeground() should definitely not be
69+
// called here unless the service is actually starting in the foreground, to avoid the
70+
// useless notification.
7171
}
7272

7373
@Override
7474
public int onStartCommand(final Intent intent, final int flags, final int startId) {
7575
if (DEBUG) {
7676
Log.d(TAG, "onStartCommand() called with: intent = [" + intent
77+
+ "], extras = [" + BundleKt.toDebugString(intent.getExtras())
7778
+ "], flags = [" + flags + "], startId = [" + startId + "]");
7879
}
7980

80-
/*
81-
Be sure that the player notification is set and the service is started in foreground,
82-
otherwise, the app may crash on Android 8+ as the service would never be put in the
83-
foreground while we said to the system we would do so
84-
The service is always requested to be started in foreground, so always creating a
85-
notification if there is no one already and starting the service in foreground should
86-
not create any issues
87-
If the service is already started in foreground, requesting it to be started shouldn't
88-
do anything
89-
*/
90-
if (player != null) {
81+
// All internal NewPipe intents used to interact with the player, that are sent to the
82+
// PlayerService using startForegroundService(), will have SHOULD_START_FOREGROUND_EXTRA,
83+
// to ensure startForeground() is called (otherwise Android will force-crash the app).
84+
if (intent.getBooleanExtra(SHOULD_START_FOREGROUND_EXTRA, false)) {
85+
if (player == null) {
86+
// make sure the player exists, in case the service was resumed
87+
player = new Player(this);
88+
}
89+
90+
// Be sure that the player notification is set and the service is started in foreground,
91+
// otherwise, the app may crash on Android 8+ as the service would never be put in the
92+
// foreground while we said to the system we would do so. The service is always
93+
// requested to be started in foreground, so always creating a notification if there is
94+
// no one already and starting the service in foreground should not create any issues.
95+
// If the service is already started in foreground, requesting it to be started
96+
// shouldn't do anything.
9197
player.UIs().get(NotificationPlayerUi.class)
9298
.ifPresent(NotificationPlayerUi::createNotificationAndStartForeground);
9399
}

app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ public void startService(final boolean playAfterConnect,
130130
// and NullPointerExceptions inside the service because the service will be
131131
// bound twice. Prevent it with unbinding first
132132
unbind(context);
133-
ContextCompat.startForegroundService(context, new Intent(context, PlayerService.class));
133+
final Intent intent = new Intent(context, PlayerService.class);
134+
intent.putExtra(PlayerService.SHOULD_START_FOREGROUND_EXTRA, true);
135+
ContextCompat.startForegroundService(context, intent);
134136
serviceConnection.doPlayAfterConnect(playAfterConnect);
135137
bind(context);
136138
}

app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public static <T> Intent getPlayerIntent(@NonNull final Context context,
9696
}
9797
intent.putExtra(Player.PLAYER_TYPE, PlayerType.MAIN.valueForIntent());
9898
intent.putExtra(Player.RESUME_PLAYBACK, resumePlayback);
99+
intent.putExtra(PlayerService.SHOULD_START_FOREGROUND_EXTRA, true);
99100

100101
return intent;
101102
}

0 commit comments

Comments
 (0)