Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Landscape fullscreen example #170

Merged
merged 7 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions android/gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@ done
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum

Expand Down Expand Up @@ -133,10 +130,13 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi

# Increase the maximum file descriptors if we can.
Expand Down Expand Up @@ -197,6 +197,10 @@ if "$cygwin" || "$msys" ; then
done
fi


# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.0.4")
classpath("com.android.tools.build:gradle:7.3.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:4.1.2")
// NOTE: Do not place your application dependencies here; they belong
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
5 changes: 5 additions & 0 deletions example/ios/BitmovinPlayerReactNativeExample/AppDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#import "Orientation.h"
#import "AppDelegate.h"

#import <React/RCTBridge.h>
Expand Down Expand Up @@ -29,6 +30,10 @@ @interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate>

@implementation AppDelegate

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [Orientation getOrientation];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTAppSetupPrepareApp(application);
Expand Down
6 changes: 6 additions & 0 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ PODS:
- React-jsinspector (0.69.6-2)
- React-logger (0.69.6-2):
- glog
- react-native-orientation-locker (1.5.0):
- React-Core
- react-native-safe-area-context (4.3.1):
- RCT-Folly
- RCTRequired
Expand Down Expand Up @@ -397,6 +399,7 @@ DEPENDENCIES:
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
Expand Down Expand Up @@ -478,6 +481,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-orientation-locker:
:path: "../node_modules/react-native-orientation-locker"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
React-perflogger:
Expand Down Expand Up @@ -547,6 +552,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: c83eedc4e1f901add32d31ea9996313bc0701816
React-jsinspector: 392a5ab785fe93b2d561729feef37a72c46f0aad
React-logger: 8daf6ad98634b54430fada5c3710515211c6115a
react-native-orientation-locker: 851f6510d8046ea2f14aa169b1e01fcd309a94ba
react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de
React-perflogger: da6bbceb96facda672b35dc7362dd6bf54ff6774
React-RCTAnimation: aa95cd5bd5418b5d8569b31775e79818110ed90b
Expand Down
4 changes: 3 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"react": "18.0.0",
"react-native": "npm:[email protected]",
"react-native-modal": "13.0.1",
"react-native-orientation-locker": "1.5.0",
"react-native-safe-area-context": "4.3.1",
"react-native-screens": "3.15.0"
"react-native-screens": "3.15.0",
"react-native-system-navigation-bar": "^2.6.1"
}
}
15 changes: 15 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import CustomPlayback from './screens/CustomPlayback';
import BasicPictureInPicture from './screens/BasicPictureInPicture';
import CustomHtmlUi from './screens/CustomHtmlUi';
import BasicFullscreenHandling from './screens/BasicFullscreenHandling';
import LandscapeFullscreenHandling from './screens/LandscapeFullscreenHandling';

export type RootStackParamsList = {
ExamplesList: {
Expand All @@ -33,6 +34,9 @@ export type RootStackParamsList = {
BasicFullscreenHandling: {
navigation: NativeStackNavigationProp<RootStackParamsList>;
};
LandscapeFullscreenHandling: {
navigation: NativeStackNavigationProp<RootStackParamsList>;
};
SubtitlePlayback: undefined;
CustomPlaybackForm: undefined;
CustomPlayback: {
Expand Down Expand Up @@ -98,6 +102,10 @@ export default function App() {
title: 'Basic Fullscreen handling',
routeName: 'BasicFullscreenHandling',
});
stackParams.data.push({
title: 'Landscape Fullscreen handling',
routeName: 'LandscapeFullscreenHandling',
});
}

return (
Expand Down Expand Up @@ -184,6 +192,13 @@ export default function App() {
options={{ title: 'Basic Fullscreen Handling' }}
/>
)}
{!Platform.isTV && (
<RootStack.Screen
name="LandscapeFullscreenHandling"
component={LandscapeFullscreenHandling}
options={{ title: 'Lanscape Fullscreen Handling' }}
/>
)}
</RootStack.Navigator>
</NavigationContainer>
);
Expand Down
171 changes: 171 additions & 0 deletions example/src/screens/LandscapeFullscreenHandling.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import React, { useCallback, useRef, useState } from 'react';
import { Platform, StatusBar, StyleSheet, View } from 'react-native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { useFocusEffect } from '@react-navigation/native';
import {
AudioSession,
Event,
FullscreenHandler,
PlayerView,
SourceType,
usePlayer,
} from 'bitmovin-player-react-native';
import { useTVGestures } from '../hooks';
import { RootStackParamsList } from '../App';
import Orientation from 'react-native-orientation-locker';
import SystemNavigationBar from 'react-native-system-navigation-bar';

type LandscapeFullscreenHandlingProps = NativeStackScreenProps<
RootStackParamsList,
'LandscapeFullscreenHandling'
>;

function prettyPrint(header: string, obj: any) {
console.log(header, JSON.stringify(obj, null, 2));
}

class SampleFullscreenHandler implements FullscreenHandler {
isFullscreenActive: boolean = true;
onFullscreen: (fullscreenMode: boolean) => void;

constructor(
isFullscreenActive: boolean,
onFullscreen: (fullscreenMode: boolean) => void
) {
this.isFullscreenActive = isFullscreenActive;
this.onFullscreen = onFullscreen;
}

enterFullscreen(): void {
this.onFullscreen(true);
this.isFullscreenActive = true;
if (Platform.OS === 'android') {
// Hides navigation and status bar on Android
SystemNavigationBar.stickyImmersive(true);
rolandkakonyi marked this conversation as resolved.
Show resolved Hide resolved
} else {
// Hides status bar on iOS
StatusBar.setHidden(true);
}
Orientation.lockToLandscape();
console.log('enter fullscreen');
}

exitFullscreen(): void {
this.onFullscreen(false);
if (Platform.OS === 'android') {
// shows navigation and status bar on Android
SystemNavigationBar.stickyImmersive(false);
} else {
// shows status bar on iOS
StatusBar.setHidden(false);
}
this.isFullscreenActive = false;
Orientation.unlockAllOrientations();
console.log('exit fullscreen');
}
}

export default function LandscapeFullscreenHandling({
navigation,
}: LandscapeFullscreenHandlingProps) {
useTVGestures();

const player = usePlayer({
playbackConfig: {
isAutoplayEnabled: true,
},
});

const [fullscreenMode, setFullscreenMode] = useState(true);
const fullscreenHandler = useRef(
new SampleFullscreenHandler(fullscreenMode, (isFullscreen: boolean) => {
console.log('on fullscreen change');
setFullscreenMode(isFullscreen);
navigation.setOptions({ headerShown: !isFullscreen });
})
).current;
useFocusEffect(
useCallback(() => {
// iOS audio session must be set to `playback` first otherwise PiP mode won't work.
//
// Usually it's desireable to set the audio's category only once during your app's main component
// initialization. This way you can guarantee that your app's audio category is properly
// configured throughout the whole lifecycle of the application.
AudioSession.setCategory('playback').catch((error) => {
// Handle any native errors that might occur while setting the audio's category.
console.log(
"[LandscapeFullscreen] Failed to set app's audio category to `playback`:\n",
error
);
});
// Load desired source configuration
player.load({
url:
Platform.OS === 'ios'
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
title: 'Art of Motion',
poster:
'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/poster.jpg',
});
return () => {
player.destroy();
};
}, [player])
);
useFocusEffect(
useCallback(() => {
return () => {
fullscreenHandler.exitFullscreen();
};
}, [fullscreenHandler])
);

const onEvent = useCallback((event: Event) => {
prettyPrint(`[${event.name}]`, event);
}, []);

const onError = useCallback(() => {
setFullscreenMode(false);
}, []);

return (
<View style={styles.container}>
<PlayerView
player={player}
isFullscreen={fullscreenMode}
style={fullscreenMode ? styles.playerFullscreen : styles.player}
fullscreenHandler={fullscreenHandler}
onFullscreenEnter={onEvent}
onFullscreenExit={onEvent}
onFullscreenEnabled={onEvent}
onFullscreenDisabled={onEvent}
onPlayerError={onError}
onSourceError={onError}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
padding: 20,
},
player: {
flex: 1,
backgroundColor: 'black',
},
playerFullscreen: {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: 'black',
},
});
10 changes: 10 additions & 0 deletions example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3478,6 +3478,11 @@ [email protected]:
prop-types "^15.6.2"
react-native-animatable "1.3.3"

[email protected]:
version "1.5.0"
resolved "https://registry.yarnpkg.com/react-native-orientation-locker/-/react-native-orientation-locker-1.5.0.tgz#324853937eed4835ecd1c8613ab2206135d908ac"
integrity sha512-4XOCGmNN4BXg5JUFjUuXpsfhPJmbA3LkQilJO1ed+6vL97teTdG2w5IEevKiqL9/hPjeWE8YYtX/YW+yp53hkg==

[email protected]:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.3.1.tgz#5cf97b25b395e0d09bc1f828920cd7da0d792ade"
Expand All @@ -3491,6 +3496,11 @@ [email protected]:
react-freeze "^1.0.0"
warn-once "^0.1.0"

react-native-system-navigation-bar@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/react-native-system-navigation-bar/-/react-native-system-navigation-bar-2.6.1.tgz#cead40f7311fe92be4921808901b7b56e9c763d8"
integrity sha512-IN5n55sEbA4oAvwUqK8oCfKKc4fXJmBzcqC/Eq8bv26gTwzk6oUiPrHtzJCSJvWyCOCt6jKuc9vDWEFTLDOLog==

"react-native@npm:[email protected]":
version "0.69.6-2"
resolved "https://registry.yarnpkg.com/react-native-tvos/-/react-native-tvos-0.69.6-2.tgz#d2214283a8ba267a2f08330274f98dbdb22d333a"
Expand Down