How to Enable Picture-in-Picture (PiP) Mode in SmartTube: A Complete Developer Guide
SmartTube enables Picture-in-Picture mode through a combination of manifest declarations in AndroidManifest.xml, runtime checks via Helpers.isPictureInPictureSupported(), and the enterPipMode() method in PlaybackActivity, which triggers when users select PiP as the background playback mode.
Picture-in-Picture (PiP) allows users to continue watching videos in a floating window while navigating other applications on their Android TV or mobile device. According to the yuliskov/SmartTube source code, implementing this feature requires coordinating Android system capabilities with the app's playback engine and activity lifecycle. The implementation spans manifest declarations, runtime permission checks, and UI state management across multiple components.
Manifest Configuration for PiP Support
Before SmartTube can enter PiP mode, the Android system requires explicit declaration in the app manifest. This informs the OS that the playback activity supports floating window behavior.
In smarttubetv/src/main/AndroidManifest.xml, the PlaybackActivity declaration includes the crucial android:supportsPictureInPicture attribute:
<activity
android:name=".tv.ui.playback.PlaybackActivity"
android:label="@string/app_name"
android:supportsPictureInPicture="true"
android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize|smallestScreenSize"
... />
Setting android:supportsPictureInPicture="true" is mandatory for Android N (API 24) and above. Without this flag, calls to enterPictureInPictureMode() will fail silently or throw exceptions.
Runtime Capability Verification
SmartTube defensively checks device capabilities before attempting to enter PiP mode. The helper method Helpers.isPictureInPictureSupported() performs runtime validation to ensure the device runs Android N (API 24) or higher and that the activity properly declares PiP support in its manifest.
This check guards against crashes on older devices or incompatible Android TV implementations. The method returns true only when the system can safely enter PiP mode, allowing the app to fall back to standard background audio playback on unsupported devices.
Implementing the PiP Entry Point
The core logic for entering PiP mode resides in PlaybackActivity.java. The enterPipMode() method orchestrates the transition, handling version-specific API differences and user preference checks.
Located in smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/playback/PlaybackActivity.java, this method demonstrates the complete flow:
@TargetApi(24)
private void enterPipMode() {
if (Helpers.isPictureInPictureSupported(this) && wannaEnterToPip()) {
try {
if (Build.VERSION.SDK_INT >= 26) {
PictureInPictureParams.Builder params = new PictureInPictureParams.Builder();
// Optional: set aspect ratio, custom actions, or source rect hint
enterPictureInPictureMode(params.build());
} else {
// Legacy API for Android N (API 24-25)
enterPictureInPictureMode();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
}
Key implementation details include:
- The
wannaEnterToPip()guard: This internal check verifies thatPlayerDatahasBACKGROUND_MODE_PIPselected and confirms the activity is not already in PiP mode. - Version branching: Android O (API 26) introduced
PictureInPictureParamsfor customizing the PiP window aspect ratio and actions. Older versions use the parameterlessenterPictureInPictureMode()method. - Exception safety: The try-catch block prevents crashes if the system denies PiP entry due to memory constraints or policy restrictions.
Configuring Background Playback Mode
PiP activation depends on the user's background playback preference stored in PlayerData. The app must explicitly set the background mode to PlayerEngine.BACKGROUND_MODE_PIP to allow the wannaEnterToPip() check to succeed.
To programmatically enable PiP as the default background behavior:
PlayerData playerData = PlayerData.instance(context);
playerData.setBackgroundMode(PlayerEngine.BACKGROUND_MODE_PIP);
This setting persists across sessions and controls whether the app enters PiP mode automatically when the user presses the home button or triggers the back action during playback. Users can also toggle this manually via Settings → Background playback → PiP in the SmartTube interface.
Handling PiP Lifecycle Events
When the system transitions to or from PiP mode, SmartTube must adapt its UI components. The PlaybackActivity overrides onPictureInPictureModeChanged() to propagate state changes to the playback fragment:
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
if (mPlaybackFragment != null) {
mPlaybackFragment.onPIPChanged(isInPictureInPictureMode);
}
}
The fragment's onPIPChanged() method then adjusts the visibility of controls, hiding full-screen overlays and displaying minimal playback controls suitable for the smaller window:
@Override
public void onPIPChanged(boolean isInPip) {
if (isInPip) {
hideFullScreenOverlay();
showMinimalControls();
} else {
showFullScreenOverlay();
}
}
Key Source Files for PiP Implementation
Understanding the complete PiP architecture requires familiarity with these specific files in the yuliskov/SmartTube repository:
smarttubetv/src/main/AndroidManifest.xml: Contains theandroid:supportsPictureInPicture="true"declaration forPlaybackActivity.smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/playback/PlaybackActivity.java: Houses theenterPipMode()entry point and lifecycle callbacks.common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/PlayerData.java: Manages theBACKGROUND_MODE_PIPpreference and persistence.common/src/main/java/com/liskovsoft/smartyoutubetv2/common/misc/Helpers.java: Provides theisPictureInPictureSupported()utility method for runtime capability detection.
Summary
Enabling Picture-in-Picture in SmartTube requires coordination across the Android manifest, runtime system checks, and user preference management:
- Declare
android:supportsPictureInPicture="true"inAndroidManifest.xmlfor the playback activity. - Verify device compatibility using
Helpers.isPictureInPictureSupported()before attempting entry. - Set the background mode to
PlayerEngine.BACKGROUND_MODE_PIPviaPlayerDatato permit PiP activation. - Implement
enterPipMode()inPlaybackActivitywith version-specific logic for Android O+ versus older versions. - Handle lifecycle changes through
onPictureInPictureModeChanged()to adapt the UI for floating window constraints.
Frequently Asked Questions
What is the minimum Android version required for PiP in SmartTube?
SmartTube requires Android N (API 24) or higher for Picture-in-Picture functionality. The Helpers.isPictureInPictureSupported() method explicitly checks for this API level, and the enterPipMode() method uses the @TargetApi(24) annotation to prevent compilation errors on older SDKs.
Why doesn't PiP activate when I press the home button?
PiP only activates when the background playback mode is explicitly set to BACKGROUND_MODE_PIP in PlayerData. If the mode is set to background audio only (BACKGROUND_MODE_SOUND) or disabled, the wannaEnterToPip() check returns false. Verify the setting in the app's preferences or programmatically set it using playerData.setBackgroundMode(PlayerEngine.BACKGROUND_MODE_PIP).
How do I customize the PiP window aspect ratio on Android O and above?
For Android O (API 26) and higher, modify the PictureInPictureParams.Builder in enterPipMode() before calling enterPictureInPictureMode(). You can set the aspect ratio using params.setAspectRatio(new Rational(width, height)) and add custom actions using params.setActions(actionsList).
Where does SmartTube handle UI changes when entering PiP mode?
UI adaptations occur in the onPIPChanged() method of the playback fragment, triggered via PlaybackActivity.onPictureInPictureModeChanged(). This pattern ensures that full-screen overlays hide and minimal controls appear immediately when the activity enters PiP mode, and reverse when returning to full screen.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →