Add full screen support to Android Exoplayer (#1730)
This commit is contained in:
		@@ -1,5 +1,8 @@
 | 
			
		||||
## Changelog
 | 
			
		||||
 | 
			
		||||
### Version 5.1.1
 | 
			
		||||
* Added support for full-screen functionality in Android Exoplayer [#1730](https://github.com/react-native-community/react-native-video/pull/1730)
 | 
			
		||||
 | 
			
		||||
### Version 5.1.0-alpha1
 | 
			
		||||
* Fixed Exoplayer doesn't work with mute=true (Android). [#1696](https://github.com/react-native-community/react-native-video/pull/1696)
 | 
			
		||||
* Added support for automaticallyWaitsToMinimizeStalling property (iOS) [#1723](https://github.com/react-native-community/react-native-video/pull/1723)
 | 
			
		||||
 
 | 
			
		||||
@@ -412,6 +412,8 @@ Note on iOS, controls are always shown when in fullscreen mode.
 | 
			
		||||
 | 
			
		||||
For Android MediaPlayer, you will need to build your own controls or use a package like [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls) or [react-native-video-player](https://github.com/cornedor/react-native-video-player).
 | 
			
		||||
 | 
			
		||||
Note on Android ExoPlayer, native controls are available by default. If needed, you can also add your controls or use a package like [react-native-video-controls].
 | 
			
		||||
 | 
			
		||||
Platforms: Android ExoPlayer, iOS, react-native-dom
 | 
			
		||||
 | 
			
		||||
#### disableFocus
 | 
			
		||||
@@ -462,7 +464,7 @@ Controls whether the player enters fullscreen on play.
 | 
			
		||||
* **false (default)** - Don't display the video in fullscreen
 | 
			
		||||
* **true** - Display the video in fullscreen
 | 
			
		||||
 | 
			
		||||
Platforms: iOS
 | 
			
		||||
Platforms: iOS, Android Exoplayer
 | 
			
		||||
 | 
			
		||||
#### fullscreenAutorotate
 | 
			
		||||
If a preferred [fullscreenOrientation](#fullscreenorientation) is set, causes the video to rotate to that orientation but permits rotation of the screen to orientation held by user. Defaults to TRUE.
 | 
			
		||||
@@ -475,6 +477,8 @@ Platforms: iOS
 | 
			
		||||
* **landscape**
 | 
			
		||||
* **portrait**
 | 
			
		||||
 | 
			
		||||
Note on Android ExoPlayer, the full-screen mode by default goes into landscape mode. Exiting from the full-screen mode will display the video in Initial orientation.
 | 
			
		||||
 | 
			
		||||
Platforms: iOS
 | 
			
		||||
 | 
			
		||||
#### headers
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								Video.js
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								Video.js
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
import React, { Component } from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, findNodeHandle} from 'react-native';
 | 
			
		||||
import { StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, UIManager, findNodeHandle, Dimensions } from 'react-native';
 | 
			
		||||
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
 | 
			
		||||
import TextTrackType from './TextTrackType';
 | 
			
		||||
import FilterType from './FilterType';
 | 
			
		||||
@@ -20,8 +20,35 @@ export default class Video extends Component {
 | 
			
		||||
    super(props);
 | 
			
		||||
 | 
			
		||||
    this.state = {
 | 
			
		||||
      showPoster: !!props.poster
 | 
			
		||||
      showPoster: !!props.poster,
 | 
			
		||||
      androidFullScreen: false,
 | 
			
		||||
      videoContainerLayout_x: 0,
 | 
			
		||||
      videoContainerLayout_y: 0
 | 
			
		||||
    };
 | 
			
		||||
    this.getDimension();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @description this is will set the width and height needs to be considered for full screen
 | 
			
		||||
   */
 | 
			
		||||
  getDimension() {
 | 
			
		||||
    if (Dimensions.get('window').width < Dimensions.get('window').height) {
 | 
			
		||||
      this.width = Math.round(Dimensions.get('window').height);
 | 
			
		||||
      this.height = Math.round(Dimensions.get('window').width);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      this.width = Math.round(Dimensions.get('window').width);
 | 
			
		||||
      this.height = Math.round(Dimensions.get('window').height);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentDidMount() {
 | 
			
		||||
    UIManager.measure(findNodeHandle(this._videoContainer), (x, y) => {
 | 
			
		||||
      this.setState({
 | 
			
		||||
        videoContainerLayout_x: x,
 | 
			
		||||
        videoContainerLayout_y: y
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setNativeProps(nativeProps) {
 | 
			
		||||
@@ -145,6 +172,7 @@ export default class Video extends Component {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  _onFullscreenPlayerWillPresent = (event) => {
 | 
			
		||||
    Platform.OS === 'android' && this.setState({ androidFullScreen: true })
 | 
			
		||||
    if (this.props.onFullscreenPlayerWillPresent) {
 | 
			
		||||
      this.props.onFullscreenPlayerWillPresent(event.nativeEvent);
 | 
			
		||||
    }
 | 
			
		||||
@@ -157,6 +185,7 @@ export default class Video extends Component {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  _onFullscreenPlayerWillDismiss = (event) => {
 | 
			
		||||
    Platform.OS === 'android' && this.setState({ androidFullScreen: false })
 | 
			
		||||
    if (this.props.onFullscreenPlayerWillDismiss) {
 | 
			
		||||
      this.props.onFullscreenPlayerWillDismiss(event.nativeEvent);
 | 
			
		||||
    }
 | 
			
		||||
@@ -313,8 +342,22 @@ export default class Video extends Component {
 | 
			
		||||
      resizeMode: this.props.posterResizeMode || 'contain',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    //androidFullScreen property will only impact on android. It will be always false for iOS.
 | 
			
		||||
    const videoStyle = this.state.androidFullScreen ? {
 | 
			
		||||
      position: 'absolute',
 | 
			
		||||
      top: 0,
 | 
			
		||||
      left: 0,
 | 
			
		||||
      width: this.width,
 | 
			
		||||
      height: this.height,
 | 
			
		||||
      backgroundColor: '#ffffff',
 | 
			
		||||
      justifyContent: "center",
 | 
			
		||||
      zIndex: 99999,
 | 
			
		||||
      marginTop: -1 * (this.state.videoContainerLayout_y ? parseFloat(this.state.videoContainerLayout_y) : 0), //margin: 0 - is not working properly. So, updated all the margin individually with 0.
 | 
			
		||||
      marginLeft: -1 * (this.state.videoContainerLayout_x ? parseFloat(this.state.videoContainerLayout_x) : 0)
 | 
			
		||||
    } : {}
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <View style={nativeProps.style}>
 | 
			
		||||
      <View ref={(videoContainer) => this._videoContainer = videoContainer} style={[nativeProps.style, videoStyle]}>
 | 
			
		||||
        <RCTVideo
 | 
			
		||||
          ref={this._assignRoot}
 | 
			
		||||
          {...nativeProps}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package com.brentvatne.exoplayer;
 | 
			
		||||
import android.annotation.SuppressLint;
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.pm.ActivityInfo;
 | 
			
		||||
import android.media.AudioManager;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
@@ -13,6 +14,7 @@ import android.view.View;
 | 
			
		||||
import android.view.Window;
 | 
			
		||||
import android.view.accessibility.CaptioningManager;
 | 
			
		||||
import android.widget.FrameLayout;
 | 
			
		||||
import android.widget.ImageView;
 | 
			
		||||
 | 
			
		||||
import com.brentvatne.react.R;
 | 
			
		||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
 | 
			
		||||
@@ -97,6 +99,7 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
    private Player.EventListener eventListener;
 | 
			
		||||
 | 
			
		||||
    private ExoPlayerView exoPlayerView;
 | 
			
		||||
    private int initialOrientation;
 | 
			
		||||
 | 
			
		||||
    private DataSource.Factory mediaDataSourceFactory;
 | 
			
		||||
    private SimpleExoPlayer player;
 | 
			
		||||
@@ -169,6 +172,7 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
    public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig config) {
 | 
			
		||||
        super(context);
 | 
			
		||||
        this.themedReactContext = context;
 | 
			
		||||
        this.initialOrientation = getResources().getConfiguration().orientation;
 | 
			
		||||
        this.eventEmitter = new VideoEventEmitter(context);
 | 
			
		||||
        this.config = config;
 | 
			
		||||
        this.bandwidthMeter = config.getBandwidthMeter();
 | 
			
		||||
@@ -292,6 +296,16 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        //Handling the fullScreenButton click event
 | 
			
		||||
        FrameLayout fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen_button);
 | 
			
		||||
        fullScreenButton.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                setFullscreen(!isFullscreen);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        updateFullScreenIcon(isFullscreen);
 | 
			
		||||
 | 
			
		||||
        // Invoking onPlayerStateChanged event for Player
 | 
			
		||||
        eventListener = new Player.EventListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
@@ -320,6 +334,33 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
        addView(playerControlView, 1, layoutParams);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Update fullscreen icon
 | 
			
		||||
     */
 | 
			
		||||
    private void updateFullScreenIcon(Boolean fullScreen) {
 | 
			
		||||
        if(playerControlView != null && player != null) {
 | 
			
		||||
            //Play the video whenever the user clicks minimize or maximise button. In order to enable the controls
 | 
			
		||||
            player.setPlayWhenReady(true);
 | 
			
		||||
            ImageView fullScreenIcon = playerControlView.findViewById(R.id.exo_fullscreen_icon);
 | 
			
		||||
            if (fullScreen) {
 | 
			
		||||
                fullScreenIcon.setImageResource(R.drawable.fullscreen_shrink);
 | 
			
		||||
            } else {
 | 
			
		||||
                fullScreenIcon.setImageResource(R.drawable.fullscreen_expand);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enable or Disable fullscreen button
 | 
			
		||||
     */
 | 
			
		||||
    private void enableFullScreenButton(Boolean enable) {
 | 
			
		||||
        if(playerControlView != null) {
 | 
			
		||||
            FrameLayout fullScreenButton = playerControlView.findViewById(R.id.exo_fullscreen_button);
 | 
			
		||||
            fullScreenButton.setAlpha(enable ? 1.0f : 0.5f);
 | 
			
		||||
            fullScreenButton.setEnabled(enable);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Update the layout
 | 
			
		||||
     * @param view  view needs to update layout
 | 
			
		||||
@@ -545,10 +586,13 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
 | 
			
		||||
    private void onStopPlayback() {
 | 
			
		||||
        if (isFullscreen) {
 | 
			
		||||
            setFullscreen(false);
 | 
			
		||||
            //When the video stopPlayback.
 | 
			
		||||
            //If the video is in fullscreen, then we will update the video to normal mode.
 | 
			
		||||
            setFullscreen(!isFullscreen);
 | 
			
		||||
        }
 | 
			
		||||
        setKeepScreenOn(false);
 | 
			
		||||
        audioManager.abandonAudioFocus(this);
 | 
			
		||||
        enableFullScreenButton(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void updateResumePosition() {
 | 
			
		||||
@@ -642,6 +686,7 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
                if (playerControlView != null) {
 | 
			
		||||
                    playerControlView.show();
 | 
			
		||||
                }
 | 
			
		||||
                enableFullScreenButton(true);
 | 
			
		||||
                break;
 | 
			
		||||
            case Player.STATE_ENDED:
 | 
			
		||||
                text += "ended";
 | 
			
		||||
@@ -1160,6 +1205,8 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
        if (fullscreen == isFullscreen) {
 | 
			
		||||
            return; // Avoid generating events when nothing is changing
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        updateFullScreenIcon(fullscreen);
 | 
			
		||||
        isFullscreen = fullscreen;
 | 
			
		||||
 | 
			
		||||
        Activity activity = themedReactContext.getCurrentActivity();
 | 
			
		||||
@@ -1178,11 +1225,17 @@ class ReactExoplayerView extends FrameLayout implements
 | 
			
		||||
                uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION
 | 
			
		||||
                        | SYSTEM_UI_FLAG_FULLSCREEN;
 | 
			
		||||
            }
 | 
			
		||||
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
 | 
			
		||||
            eventEmitter.fullscreenWillPresent();
 | 
			
		||||
            decorView.setSystemUiVisibility(uiOptions);
 | 
			
		||||
            eventEmitter.fullscreenDidPresent();
 | 
			
		||||
        } else {
 | 
			
		||||
            uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
 | 
			
		||||
            //orientation, 1 is for Portrait and 2 for Landscape.
 | 
			
		||||
            if(this.initialOrientation == 1)
 | 
			
		||||
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 | 
			
		||||
            else
 | 
			
		||||
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
 | 
			
		||||
            eventEmitter.fullscreenWillDismiss();
 | 
			
		||||
            decorView.setSystemUiVisibility(uiOptions);
 | 
			
		||||
            eventEmitter.fullscreenDidDismiss();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								android-exoplayer/src/main/res/drawable/fullscreen_expand.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android-exoplayer/src/main/res/drawable/fullscreen_expand.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 365 B  | 
							
								
								
									
										
											BIN
										
									
								
								android-exoplayer/src/main/res/drawable/fullscreen_shrink.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								android-exoplayer/src/main/res/drawable/fullscreen_shrink.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 358 B  | 
@@ -71,6 +71,22 @@
 | 
			
		||||
            android:paddingRight="4dp"
 | 
			
		||||
            android:includeFontPadding="false"
 | 
			
		||||
            android:textColor="#FFBEBEBE"/>
 | 
			
		||||
        <FrameLayout
 | 
			
		||||
            android:id="@+id/exo_fullscreen_button"
 | 
			
		||||
            android:layout_width="32dp"
 | 
			
		||||
            android:layout_height="32dp"
 | 
			
		||||
            android:layout_gravity="right">
 | 
			
		||||
 | 
			
		||||
            <ImageView
 | 
			
		||||
                android:id="@+id/exo_fullscreen_icon"
 | 
			
		||||
                android:layout_width="18dp"
 | 
			
		||||
                android:layout_height="18dp"
 | 
			
		||||
                android:layout_gravity="center"
 | 
			
		||||
                android:adjustViewBounds="true"
 | 
			
		||||
                android:scaleType="fitCenter"
 | 
			
		||||
                android:src="@drawable/fullscreen_expand"/>
 | 
			
		||||
 | 
			
		||||
        </FrameLayout>
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user