Skip to main content

Full Screen Integration

The most common pattern: the channel takes the entire screen with a fullscreen player overlay.

Basic Setup

import React, { useRef, useState } from 'react';
import { SafeAreaView, StatusBar, StyleSheet } from 'react-native';
import {
BBChannel,
BBChannelRef,
BBFullscreenPlayer,
BBMediaInfo,
} from '@bluebillywig/react-native-channel';

function ChannelScreen() {
const channelRef = useRef<BBChannelRef>(null);
const [media, setMedia] = useState<BBMediaInfo | null>(null);

return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<BBChannel
ref={channelRef}
channelUrl="https://demo.bbvms.com/ch/channel_name.json"
handleBackButton={true}
onMediaRequest={(mediaInfo) => setMedia(mediaInfo)}
style={styles.channel}
/>
<BBFullscreenPlayer
media={media}
visible={media !== null}
onClose={() => setMedia(null)}
/>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
channel: {
flex: 1,
},
});

Loading State

Show a loading overlay while the channel initializes:

function ChannelScreen() {
const channelRef = useRef<BBChannelRef>(null);
const [media, setMedia] = useState<BBMediaInfo | null>(null);
const [loading, setLoading] = useState(true);

return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<BBChannel
ref={channelRef}
channelUrl="https://demo.bbvms.com/ch/channel_name.json"
handleBackButton={true}
onReady={() => setLoading(false)}
onMediaRequest={(mediaInfo) => setMedia(mediaInfo)}
style={styles.channel}
/>
{loading && (
<View style={styles.loadingOverlay}>
<ActivityIndicator size="large" color="#fff" />
</View>
)}
<BBFullscreenPlayer
media={media}
visible={media !== null}
onClose={() => setMedia(null)}
/>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
channel: {
flex: 1,
},
loadingOverlay: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000',
},
});

Android Back Button

Simple: Automatic Handling

The easiest approach — set handleBackButton={true} and the SDK handles everything:

<BBChannel
ref={channelRef}
channelUrl="https://demo.bbvms.com/ch/channel_name.json"
handleBackButton={true}
onMediaRequest={(mediaInfo) => setMedia(mediaInfo)}
/>

When the user presses the Android back button:

  1. If the fullscreen player is open, it closes
  2. If the channel can go back (detail page → main), it navigates back
  3. Otherwise, the default back behavior (exit app) runs

Advanced: Manual with Refs

For custom logic (e.g., confirming exit), handle back navigation manually using refs:

import { BackHandler } from 'react-native';

function ChannelScreen() {
const channelRef = useRef<BBChannelRef>(null);
const [media, setMedia] = useState<BBMediaInfo | null>(null);
// Use a ref to avoid stale closures in BackHandler
const canGoBackRef = useRef(false);

useEffect(() => {
const handler = BackHandler.addEventListener('hardwareBackPress', () => {
// Close player first
if (media) {
setMedia(null);
return true;
}
// Then try channel back navigation
if (canGoBackRef.current) {
channelRef.current?.goBack();
return true;
}
// Let the system handle it (exit app)
return false;
});
return () => handler.remove();
}, [media]);

return (
<SafeAreaView style={styles.container}>
<BBChannel
ref={channelRef}
channelUrl="https://demo.bbvms.com/ch/channel_name.json"
onCanGoBackChange={(canGoBack) => {
canGoBackRef.current = canGoBack;
}}
onMediaRequest={(mediaInfo) => setMedia(mediaInfo)}
/>
<BBFullscreenPlayer
media={media}
visible={media !== null}
onClose={() => setMedia(null)}
/>
</SafeAreaView>
);
}
Why refs instead of state?

BackHandler captures the state value at the time the listener is registered. If you use useState for canGoBack, rapid back presses may read a stale value. A ref always returns the current value. See Back Navigation for details.

State Persistence

Save and restore the user's position with AsyncStorage:

import AsyncStorage from '@react-native-async-storage/async-storage';
import { BBNavigationState } from '@bluebillywig/react-native-channel';

const STORAGE_KEY = '@channel_nav_state';

function ChannelScreen() {
const channelRef = useRef<BBChannelRef>(null);
const [media, setMedia] = useState<BBMediaInfo | null>(null);
const [initialState, setInitialState] = useState<BBNavigationState | undefined>();
const [ready, setReady] = useState(false);

// Load saved state on mount
useEffect(() => {
AsyncStorage.getItem(STORAGE_KEY).then((json) => {
if (json) {
setInitialState(JSON.parse(json));
}
setReady(true);
});
}, []);

if (!ready) return null;

return (
<SafeAreaView style={styles.container}>
<BBChannel
ref={channelRef}
channelUrl="https://demo.bbvms.com/ch/channel_name.json"
handleBackButton={true}
initialNavigationState={initialState}
onNavigationStateChange={(state) => {
AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(state));
}}
onMediaRequest={(mediaInfo) => setMedia(mediaInfo)}
/>
<BBFullscreenPlayer
media={media}
visible={media !== null}
onClose={() => setMedia(null)}
/>
</SafeAreaView>
);
}

Key Points

  • SafeAreaView — Wrap the channel in SafeAreaView to avoid notches and system UI. The SDK also has built-in safe area support via the safeAreaEdges prop (see Safe Areas).
  • StatusBar — Set barStyle="light-content" for dark channel backgrounds.
  • Orientation — The channel is responsive and adapts to both portrait and landscape. Lock orientation at the app level if needed. The fullscreen player handles orientation independently.
  • Background color — Set the container background to match the channel theme to avoid white flashes during load.