chore(android): rework view type (#3940)
This commit is contained in:
parent
6e1337689a
commit
b431d09e2f
19
android/src/main/java/com/brentvatne/common/api/ViewType.kt
Normal file
19
android/src/main/java/com/brentvatne/common/api/ViewType.kt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.brentvatne.common.api
|
||||||
|
|
||||||
|
internal object ViewType {
|
||||||
|
/**
|
||||||
|
* View used will be a TextureView.
|
||||||
|
*/
|
||||||
|
const val VIEW_TYPE_TEXTURE = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View used will be a SurfaceView.
|
||||||
|
*/
|
||||||
|
const val VIEW_TYPE_SURFACE = 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View used will be a SurfaceView with secure flag set.
|
||||||
|
*/
|
||||||
|
const val VIEW_TYPE_SURFACE_SECURE = 2
|
||||||
|
annotation class ViewType
|
||||||
|
}
|
@ -26,12 +26,14 @@ import android.widget.FrameLayout;
|
|||||||
|
|
||||||
import com.brentvatne.common.api.ResizeMode;
|
import com.brentvatne.common.api.ResizeMode;
|
||||||
import com.brentvatne.common.api.SubtitleStyle;
|
import com.brentvatne.common.api.SubtitleStyle;
|
||||||
|
import com.brentvatne.common.api.ViewType;
|
||||||
|
import com.brentvatne.common.toolbox.DebugLog;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
||||||
|
private final static String TAG = "ExoPlayerView";
|
||||||
private View surfaceView;
|
private View surfaceView;
|
||||||
private final View shutterView;
|
private final View shutterView;
|
||||||
private final SubtitleView subtitleLayout;
|
private final SubtitleView subtitleLayout;
|
||||||
@ -42,8 +44,7 @@ public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
private final ViewGroup.LayoutParams layoutParams;
|
private final ViewGroup.LayoutParams layoutParams;
|
||||||
private final FrameLayout adOverlayFrameLayout;
|
private final FrameLayout adOverlayFrameLayout;
|
||||||
|
|
||||||
private boolean useTextureView = true;
|
private @ViewType.ViewType int viewType = ViewType.VIEW_TYPE_SURFACE;
|
||||||
private boolean useSecureView = false;
|
|
||||||
private boolean hideShutterView = false;
|
private boolean hideShutterView = false;
|
||||||
|
|
||||||
public ExoPlayerView(Context context) {
|
public ExoPlayerView(Context context) {
|
||||||
@ -81,7 +82,7 @@ public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
subtitleLayout.setUserDefaultStyle();
|
subtitleLayout.setUserDefaultStyle();
|
||||||
subtitleLayout.setUserDefaultTextSize();
|
subtitleLayout.setUserDefaultTextSize();
|
||||||
|
|
||||||
updateSurfaceView();
|
updateSurfaceView(viewType);
|
||||||
|
|
||||||
adOverlayFrameLayout = new FrameLayout(context);
|
adOverlayFrameLayout = new FrameLayout(context);
|
||||||
|
|
||||||
@ -134,21 +135,28 @@ public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
shutterView.setBackgroundColor(color);
|
shutterView.setBackgroundColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSurfaceView() {
|
public void updateSurfaceView(@ViewType.ViewType int viewType) {
|
||||||
View view;
|
this.viewType = viewType;
|
||||||
if (!useTextureView || useSecureView) {
|
boolean viewNeedRefresh = false;
|
||||||
view = new SurfaceView(context);
|
if (viewType == ViewType.VIEW_TYPE_SURFACE || viewType == ViewType.VIEW_TYPE_SURFACE_SECURE) {
|
||||||
if (useSecureView) {
|
if (!(surfaceView instanceof SurfaceView)) {
|
||||||
((SurfaceView)view).setSecure(true);
|
surfaceView = new SurfaceView(context);
|
||||||
|
viewNeedRefresh = true;
|
||||||
|
}
|
||||||
|
((SurfaceView)surfaceView).setSecure(viewType == ViewType.VIEW_TYPE_SURFACE_SECURE);
|
||||||
|
} else if (viewType == ViewType.VIEW_TYPE_TEXTURE) {
|
||||||
|
if (!(surfaceView instanceof TextureView)) {
|
||||||
|
surfaceView = new TextureView(context);
|
||||||
|
viewNeedRefresh = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
view = new TextureView(context);
|
|
||||||
// Support opacity properly:
|
// Support opacity properly:
|
||||||
((TextureView) view).setOpaque(false);
|
((TextureView) surfaceView).setOpaque(false);
|
||||||
|
} else {
|
||||||
|
DebugLog.wtf(TAG, "wtf is this texture " + viewType);
|
||||||
}
|
}
|
||||||
view.setLayoutParams(layoutParams);
|
if (viewNeedRefresh) {
|
||||||
|
surfaceView.setLayoutParams(layoutParams);
|
||||||
|
|
||||||
surfaceView = view;
|
|
||||||
if (layout.getChildAt(0) != null) {
|
if (layout.getChildAt(0) != null) {
|
||||||
layout.removeViewAt(0);
|
layout.removeViewAt(0);
|
||||||
}
|
}
|
||||||
@ -158,6 +166,7 @@ public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
setVideoView();
|
setVideoView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateShutterViewVisibility() {
|
private void updateShutterViewVisibility() {
|
||||||
shutterView.setVisibility(this.hideShutterView ? View.INVISIBLE : View.VISIBLE);
|
shutterView.setVisibility(this.hideShutterView ? View.INVISIBLE : View.VISIBLE);
|
||||||
@ -211,20 +220,6 @@ public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseTextureView(boolean useTextureView) {
|
|
||||||
if (useTextureView != this.useTextureView) {
|
|
||||||
this.useTextureView = useTextureView;
|
|
||||||
updateSurfaceView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void useSecureView(boolean useSecureView) {
|
|
||||||
if (useSecureView != this.useSecureView) {
|
|
||||||
this.useSecureView = useSecureView;
|
|
||||||
updateSurfaceView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHideShutterView(boolean hideShutterView) {
|
public void setHideShutterView(boolean hideShutterView) {
|
||||||
this.hideShutterView = hideShutterView;
|
this.hideShutterView = hideShutterView;
|
||||||
updateShutterViewVisibility();
|
updateShutterViewVisibility();
|
||||||
|
@ -589,6 +589,10 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setViewType(int viewType) {
|
||||||
|
exoPlayerView.updateSurfaceView(viewType);
|
||||||
|
}
|
||||||
|
|
||||||
private class RNVLoadControl extends DefaultLoadControl {
|
private class RNVLoadControl extends DefaultLoadControl {
|
||||||
private final int availableHeapInBytes;
|
private final int availableHeapInBytes;
|
||||||
private final Runtime runtime;
|
private final Runtime runtime;
|
||||||
@ -2243,15 +2247,6 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
updateFullScreenButtonVisibility();
|
updateFullScreenButtonVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseTextureView(boolean useTextureView) {
|
|
||||||
boolean finallyUseTextureView = useTextureView && drmProps == null;
|
|
||||||
exoPlayerView.setUseTextureView(finallyUseTextureView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void useSecureView(boolean useSecureView) {
|
|
||||||
exoPlayerView.useSecureView(useSecureView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHideShutterView(boolean hideShutterView) {
|
public void setHideShutterView(boolean hideShutterView) {
|
||||||
exoPlayerView.setHideShutterView(hideShutterView);
|
exoPlayerView.setHideShutterView(hideShutterView);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import com.brentvatne.common.api.ResizeMode;
|
|||||||
import com.brentvatne.common.api.SideLoadedTextTrackList;
|
import com.brentvatne.common.api.SideLoadedTextTrackList;
|
||||||
import com.brentvatne.common.api.Source;
|
import com.brentvatne.common.api.Source;
|
||||||
import com.brentvatne.common.api.SubtitleStyle;
|
import com.brentvatne.common.api.SubtitleStyle;
|
||||||
|
import com.brentvatne.common.api.ViewType;
|
||||||
import com.brentvatne.common.react.VideoEventEmitter;
|
import com.brentvatne.common.react.VideoEventEmitter;
|
||||||
import com.brentvatne.common.toolbox.DebugLog;
|
import com.brentvatne.common.toolbox.DebugLog;
|
||||||
import com.brentvatne.common.toolbox.ReactBridgeUtils;
|
import com.brentvatne.common.toolbox.ReactBridgeUtils;
|
||||||
@ -69,8 +70,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
private static final String PROP_DISABLE_DISCONNECT_ERROR = "disableDisconnectError";
|
private static final String PROP_DISABLE_DISCONNECT_ERROR = "disableDisconnectError";
|
||||||
private static final String PROP_FOCUSABLE = "focusable";
|
private static final String PROP_FOCUSABLE = "focusable";
|
||||||
private static final String PROP_FULLSCREEN = "fullscreen";
|
private static final String PROP_FULLSCREEN = "fullscreen";
|
||||||
private static final String PROP_USE_TEXTURE_VIEW = "useTextureView";
|
private static final String PROP_VIEW_TYPE = "viewType";
|
||||||
private static final String PROP_SECURE_VIEW = "useSecureView";
|
|
||||||
private static final String PROP_SELECTED_VIDEO_TRACK = "selectedVideoTrack";
|
private static final String PROP_SELECTED_VIDEO_TRACK = "selectedVideoTrack";
|
||||||
private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type";
|
private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type";
|
||||||
private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value";
|
private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value";
|
||||||
@ -121,7 +121,6 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
public void setDRM(final ReactExoplayerView videoView, @Nullable ReadableMap drm) {
|
public void setDRM(final ReactExoplayerView videoView, @Nullable ReadableMap drm) {
|
||||||
DRMProps drmProps = DRMProps.parse(drm);
|
DRMProps drmProps = DRMProps.parse(drm);
|
||||||
videoView.setDrm(drmProps);
|
videoView.setDrm(drmProps);
|
||||||
videoView.setUseTextureView(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_SRC)
|
@ReactProp(name = PROP_SRC)
|
||||||
@ -301,14 +300,9 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
videoView.setFullscreen(fullscreen);
|
videoView.setFullscreen(fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_USE_TEXTURE_VIEW, defaultBoolean = true)
|
@ReactProp(name = PROP_VIEW_TYPE, defaultInt = ViewType.VIEW_TYPE_SURFACE)
|
||||||
public void setUseTextureView(final ReactExoplayerView videoView, final boolean useTextureView) {
|
public void setViewType(final ReactExoplayerView videoView, final int viewType) {
|
||||||
videoView.setUseTextureView(useTextureView);
|
videoView.setViewType(viewType);
|
||||||
}
|
|
||||||
|
|
||||||
@ReactProp(name = PROP_SECURE_VIEW, defaultBoolean = true)
|
|
||||||
public void useSecureView(final ReactExoplayerView videoView, final boolean useSecureView) {
|
|
||||||
videoView.useSecureView(useSecureView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_HIDE_SHUTTER_VIEW, defaultBoolean = false)
|
@ReactProp(name = PROP_HIDE_SHUTTER_VIEW, defaultBoolean = false)
|
||||||
|
@ -888,6 +888,9 @@ To customize the notification controls you can use `metadata` property in the `s
|
|||||||
|
|
||||||
### `useSecureView`
|
### `useSecureView`
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> deprecated, use viewType instead
|
||||||
|
|
||||||
<PlatformsList types={['Android']} />
|
<PlatformsList types={['Android']} />
|
||||||
|
|
||||||
Force the output to a SurfaceView and enables the secure surface.
|
Force the output to a SurfaceView and enables the secure surface.
|
||||||
@ -899,8 +902,13 @@ SurfaceView is is the only one that can be labeled as secure.
|
|||||||
- **true** - Use security
|
- **true** - Use security
|
||||||
- **false (default)** - Do not use security
|
- **false (default)** - Do not use security
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### `useTextureView`
|
### `useTextureView`
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> deprecated, use viewType instead
|
||||||
|
|
||||||
<PlatformsList types={['Android']} />
|
<PlatformsList types={['Android']} />
|
||||||
|
|
||||||
Controls whether to output to a TextureView or SurfaceView.
|
Controls whether to output to a TextureView or SurfaceView.
|
||||||
@ -915,6 +923,18 @@ useTextureView can only be set at same time you're setting the source.
|
|||||||
- **true (default)** - Use a TextureView
|
- **true (default)** - Use a TextureView
|
||||||
- **false** - Use a SurfaceView
|
- **false** - Use a SurfaceView
|
||||||
|
|
||||||
|
### `viewType`
|
||||||
|
|
||||||
|
<PlatformsList types={['Android']} />
|
||||||
|
|
||||||
|
Allow to explicitly specify view type.
|
||||||
|
This flag replace `useSecureView` and `useTextureView` fields.
|
||||||
|
There are 3 available values:
|
||||||
|
- 'textureView': The video is rendered in a texture view. it allows mapping the view on a texture (useful for 3D).
|
||||||
|
DRM playback is not supported on textureView, if drm prop is provided, the suface will be transformed to a SurfaceView.
|
||||||
|
- 'surfaceView' (default): The video is rendered in a surface. take less resources to be rendered.
|
||||||
|
- 'secureView': The video is rendered in a surface which disallow taking screenshot of the video
|
||||||
|
|
||||||
### `volume`
|
### `volume`
|
||||||
|
|
||||||
<PlatformsList types={['All']} />
|
<PlatformsList types={['All']} />
|
||||||
|
@ -44,11 +44,12 @@ import {
|
|||||||
resolveAssetSourceForVideo,
|
resolveAssetSourceForVideo,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import {VideoManager} from './specs/VideoNativeComponent';
|
import {VideoManager} from './specs/VideoNativeComponent';
|
||||||
import type {
|
import {
|
||||||
OnLoadData,
|
type OnLoadData,
|
||||||
OnTextTracksData,
|
type OnTextTracksData,
|
||||||
OnReceiveAdEventData,
|
type OnReceiveAdEventData,
|
||||||
ReactVideoProps,
|
type ReactVideoProps,
|
||||||
|
ViewType,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export type VideoSaveData = {
|
export type VideoSaveData = {
|
||||||
@ -84,6 +85,9 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
|||||||
selectedVideoTrack,
|
selectedVideoTrack,
|
||||||
selectedAudioTrack,
|
selectedAudioTrack,
|
||||||
selectedTextTrack,
|
selectedTextTrack,
|
||||||
|
useTextureView,
|
||||||
|
useSecureView,
|
||||||
|
viewType,
|
||||||
onLoadStart,
|
onLoadStart,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
@ -571,6 +575,37 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const _viewType = useMemo(() => {
|
||||||
|
const hasValidDrmProp =
|
||||||
|
drm !== undefined && Object.keys(drm).length !== 0;
|
||||||
|
|
||||||
|
const shallForceViewType =
|
||||||
|
hasValidDrmProp && (viewType === ViewType.TEXTURE || useTextureView);
|
||||||
|
|
||||||
|
if (shallForceViewType) {
|
||||||
|
console.warn(
|
||||||
|
'cannot use DRM on texture view. please set useTextureView={false}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (useSecureView && useTextureView) {
|
||||||
|
console.warn(
|
||||||
|
'cannot use SecureView on texture view. please set useTextureView={false}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shallForceViewType
|
||||||
|
? useSecureView
|
||||||
|
? ViewType.SURFACE_SECURE
|
||||||
|
: ViewType.SURFACE // check if we should force the type to Surface due to DRM
|
||||||
|
: viewType
|
||||||
|
? viewType // else use ViewType from source
|
||||||
|
: useSecureView // else infer view type from useSecureView and useTextureView
|
||||||
|
? ViewType.SURFACE_SECURE
|
||||||
|
: useTextureView
|
||||||
|
? ViewType.TEXTURE
|
||||||
|
: ViewType.SURFACE;
|
||||||
|
}, [drm, useSecureView, useTextureView, viewType]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={style}>
|
<View style={style}>
|
||||||
<NativeVideoComponent
|
<NativeVideoComponent
|
||||||
@ -651,6 +686,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
|||||||
onControlsVisibilityChange={
|
onControlsVisibilityChange={
|
||||||
onControlsVisibilityChange ? _onControlsVisibilityChange : undefined
|
onControlsVisibilityChange ? _onControlsVisibilityChange : undefined
|
||||||
}
|
}
|
||||||
|
viewType={_viewType}
|
||||||
/>
|
/>
|
||||||
{hasPoster && showPoster ? (
|
{hasPoster && showPoster ? (
|
||||||
<Image style={posterStyle} source={{uri: poster}} />
|
<Image style={posterStyle} source={{uri: poster}} />
|
||||||
|
@ -337,8 +337,7 @@ export interface VideoNativeProps extends ViewProps {
|
|||||||
minLoadRetryCount?: Int32; // Android
|
minLoadRetryCount?: Int32; // Android
|
||||||
reportBandwidth?: boolean; //Android
|
reportBandwidth?: boolean; //Android
|
||||||
subtitleStyle?: SubtitleStyle; // android
|
subtitleStyle?: SubtitleStyle; // android
|
||||||
useTextureView?: boolean; // Android
|
viewType?: Int32; // Android
|
||||||
useSecureView?: boolean; // Android
|
|
||||||
bufferingStrategy?: BufferingStrategyType; // Android
|
bufferingStrategy?: BufferingStrategyType; // Android
|
||||||
controlsStyles?: ControlsStyles; // Android
|
controlsStyles?: ControlsStyles; // Android
|
||||||
onControlsVisibilityChange?: DirectEventHandler<OnControlsVisibilityChange>;
|
onControlsVisibilityChange?: DirectEventHandler<OnControlsVisibilityChange>;
|
||||||
|
11
src/types/ViewType.ts
Normal file
11
src/types/ViewType.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Define Available view type for android
|
||||||
|
* these values shall match android spec, see ViewType.kt
|
||||||
|
*/
|
||||||
|
enum ResizeMode {
|
||||||
|
TEXTURE = 0,
|
||||||
|
SURFACE = 1,
|
||||||
|
SURFACE_SECURE = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResizeMode;
|
@ -5,5 +5,6 @@ export * from './language';
|
|||||||
export {default as Orientation} from './Orientation';
|
export {default as Orientation} from './Orientation';
|
||||||
export {default as ResizeMode} from './ResizeMode';
|
export {default as ResizeMode} from './ResizeMode';
|
||||||
export {default as TextTrackType} from './TextTrackType';
|
export {default as TextTrackType} from './TextTrackType';
|
||||||
|
export {default as ViewType} from './ViewType';
|
||||||
export * from './video';
|
export * from './video';
|
||||||
export * from '../specs/VideoNativeComponent';
|
export * from '../specs/VideoNativeComponent';
|
||||||
|
@ -3,6 +3,7 @@ import type {ReactVideoEvents} from './events';
|
|||||||
import type {StyleProp, ViewProps, ViewStyle} from 'react-native';
|
import type {StyleProp, ViewProps, ViewStyle} from 'react-native';
|
||||||
import type VideoResizeMode from './ResizeMode';
|
import type VideoResizeMode from './ResizeMode';
|
||||||
import type FilterType from './FilterType';
|
import type FilterType from './FilterType';
|
||||||
|
import type ViewType from './ViewType';
|
||||||
|
|
||||||
export type Headers = Record<string, string>;
|
export type Headers = Record<string, string>;
|
||||||
|
|
||||||
@ -256,8 +257,9 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
|
|||||||
shutterColor?: string; // Android
|
shutterColor?: string; // Android
|
||||||
textTracks?: TextTracks;
|
textTracks?: TextTracks;
|
||||||
testID?: string;
|
testID?: string;
|
||||||
useTextureView?: boolean; // Android
|
viewType?: ViewType;
|
||||||
useSecureView?: boolean; // Android
|
useTextureView?: boolean; // Android // deprecated
|
||||||
|
useSecureView?: boolean; // Android // deprecated
|
||||||
volume?: number;
|
volume?: number;
|
||||||
localSourceEncryptionKeyScheme?: string;
|
localSourceEncryptionKeyScheme?: string;
|
||||||
debug?: DebugConfig;
|
debug?: DebugConfig;
|
||||||
|
Loading…
Reference in New Issue
Block a user