diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b0312b30..9284cecf 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -10,8 +10,7 @@ Describe what you wanted to happen ### Platform Which player are you experiencing the problem on: * iOS -* Android ExoPlayer -* Android MediaPlayer +* Android * Windows UWP * Windows WPF diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ac2d1e3e..54296c23 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -18,12 +18,11 @@ assignees: '' ## Platform Which player are you experiencing the problem on: * iOS -* Android ExoPlayer -* Android MediaPlayer +* Android * Windows UWP * Windows WPF diff --git a/API.md b/API.md index 13eb89c0..46053502 100644 --- a/API.md +++ b/API.md @@ -111,14 +111,7 @@ Or if you have trouble, make the following additions to the given files manually #### **android/settings.gradle** -The newer ExoPlayer library will work for most people. - -```gradle -include ':react-native-video' -project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer') -``` - -If you need to use the old Android MediaPlayer based player, use the following instead: +Add player source in build configuration ```gradle include ':react-native-video' @@ -302,29 +295,29 @@ var styles = StyleSheet.create({ |[allowsExternalPlayback](#allowsexternalplayback) |iOS | |[audioOnly](#audioonly)|All | |[automaticallyWaitsToMinimizeStalling](#automaticallyWaitsToMinimizeStalling) | iOS|\ -|[backBufferDurationMs](#backBufferDurationMs)| Android Exoplayer| -|[bufferConfig](#bufferconfig)|Android ExoPlayer| -|[contentStartTime](#contentStartTime)| Android Exoplayer| -|[controls](#controls)|Android ExoPlayer, iOS, react-native-dom| -|[currentPlaybackTime](#currentPlaybackTime)|Android Exoplayer| -|[disableFocus](#disableFocus)|Android Exoplayer, iOS| -|[disableDisconnectError](#disableDisconnectError)|Android Exoplayer| +|[backBufferDurationMs](#backBufferDurationMs)| Android | +|[bufferConfig](#bufferconfig)|Android| +|[contentStartTime](#contentStartTime)| Android | +|[controls](#controls)|Android, iOS, react-native-dom| +|[currentPlaybackTime](#currentPlaybackTime)|Android| +|[disableFocus](#disableFocus)|Android, iOS| +|[disableDisconnectError](#disableDisconnectError)|Android| |[filter](#filter)|iOS| |[filterEnabled](#filterEnabled)|iOS| |[fullscreen](#fullscreen)|iOS| |[fullscreenAutorotate](#fullscreenautorotate)|iOS| |[fullscreenOrientation](#fullscreenorientation)|iOS| -|[headers](#headers)|Android ExoPlayer| -|[hideShutterView](#hideshutterview)|Android ExoPlayer| +|[headers](#headers)|Android| +|[hideShutterView](#hideshutterview)|Android| |[id](#id)|react-native-dom| |[ignoreSilentSwitch](#ignoresilentswitch)|iOS| -|[maxBitRate](#maxbitrate)|Android ExoPlayer, iOS| -|[minLoadRetryCount](#minLoadRetryCount)|Android ExoPlayer| +|[maxBitRate](#maxbitrate)|Android, iOS| +|[minLoadRetryCount](#minLoadRetryCount)|Android| |[mixWithOthers](#mixWithOthers)|iOS| |[muted](#muted)|All| |[paused](#paused)|All| |[pictureInPicture](#pictureinpicture)|iOS| -|[playInBackground](#playinbackground)|Android ExoPlayer, Android MediaPlayer, iOS| +|[playInBackground](#playinbackground)|Android, iOS| |[playWhenInactive](#playwheninactive)|iOS| |[poster](#poster)|All| |[posterResizeMode](#posterresizemode)|All| @@ -333,17 +326,16 @@ var styles = StyleSheet.create({ |[progressUpdateInterval](#progressupdateinterval)|All| |[rate](#rate)|All| |[repeat](#repeat)|All| -|[reportBandwidth](#reportbandwidth)|Android ExoPlayer| -|[resizeMode](#resizemode)|Android ExoPlayer, Android MediaPlayer, iOS, Windows UWP| -|[selectedAudioTrack](#selectedaudiotrack)|Android ExoPlayer, iOS| -|[selectedTextTrack](#selectedtexttrack)|Android ExoPlayer, iOS| -|[selectedVideoTrack](#selectedvideotrack)|Android ExoPlayer| +|[reportBandwidth](#reportbandwidth)|Android| +|[resizeMode](#resizemode)|Android, iOS, Windows UWP| +|[selectedAudioTrack](#selectedaudiotrack)|Android, iOS| +|[selectedTextTrack](#selectedtexttrack)|Android, iOS| +|[selectedVideoTrack](#selectedvideotrack)|Android| |[source](#source)|All| -|[stereoPan](#stereopan)|Android MediaPlayer| -|[textTracks](#texttracks)|Android ExoPlayer, iOS| -|[trackId](#trackId)|Android ExoPlayer| -|[useTextureView](#usetextureview)|Android ExoPlayer| -|[useSecureView](#useSecureView)|Android Exoplayer| +|[textTracks](#texttracks)|Android, iOS| +|[trackId](#trackId)|Android| +|[useTextureView](#usetextureview)|Android| +|[useSecureView](#useSecureView)|Android| |[volume](#volume)|All| |[localSourceEncryptionKeyScheme](#localSourceEncryptionKeyScheme)|All| @@ -351,31 +343,31 @@ var styles = StyleSheet.create({ ### Event props | Name |Plateforms Support | |--|--| -|[onAudioBecomingNoisy](#onaudiobecomingnoisy)|Android ExoPlayer, iOS| -|[onBandwidthUpdate](#onbandwidthupdate)|Android ExoPlayer| -|[onBuffer](#onbuffer)|Android ExoPlayer, iOS| +|[onAudioBecomingNoisy](#onaudiobecomingnoisy)|Android, iOS| +|[onBandwidthUpdate](#onbandwidthupdate)|Android| +|[onBuffer](#onbuffer)|Android, iOS| |[onEnd](#onend)|All| |[onExternalPlaybackChange](#onexternalplaybackchange)|iOS| -|[onFullscreenPlayerWillPresent](#onfullscreenplayerwillpresent)|Android ExoPlayer, Android MediaPlayer, iOS| -|[onFullscreenPlayerDidPresent](#onfullscreenplayerdidpresent)|Android ExoPlayer, Android MediaPlayer, iOS| -|[onFullscreenPlayerWillDismiss](#onfullscreenplayerwilldismiss)|Android ExoPlayer, Android MediaPlayer, iOS| -|[onFullscreenPlayerDidDismiss](#onfullscreenplayerdiddismiss)|Android ExoPlayer, Android MediaPlayer, iOS| +|[onFullscreenPlayerWillPresent](#onfullscreenplayerwillpresent)|Android, iOS| +|[onFullscreenPlayerDidPresent](#onfullscreenplayerdidpresent)|Android, iOS| +|[onFullscreenPlayerWillDismiss](#onfullscreenplayerwilldismiss)|Android, iOS| +|[onFullscreenPlayerDidDismiss](#onfullscreenplayerdiddismiss)|Android, iOS| |[onLoad](#onload)|All| |[onLoadStart](#onloadstart)|All| -|[onReadyForDisplay](#onreadyfordisplay)|Android ExoPlayer, Android MediaPlayer, iOS, Web| +|[onReadyForDisplay](#onreadyfordisplay)|Android, iOS, Web| |[onPictureInPictureStatusChanged](#onpictureinpicturestatuschanged)|iOS| |[onPlaybackRateChange](#onplaybackratechange)|All| |[onProgress](#onprogress)|All| -|[onSeek](#onseek)|Android ExoPlayer, Android MediaPlayer, iOS, Windows UWP| +|[onSeek](#onseek)|Android, iOS, Windows UWP| |[onRestoreUserInterfaceForPictureInPictureStop](#onrestoreuserinterfaceforpictureinpicturestop)|iOS| -|[onTimedMetadata](#ontimedmetadata)|Android ExoPlayer, Android MediaPlayer, iOS| +|[onTimedMetadata](#ontimedmetadata)|Android, iOS| ### Methods | Name |Plateforms Support | |--|--| -|[dismissFullscreenPlayer](#dismissfullscreenplayer)|Android ExoPlayer, Android MediaPlayer, iOS| -|[presentFullscreenPlayer](#presentfullscreenplayer)|Android ExoPlayer, Android MediaPlayer, iOS| +|[dismissFullscreenPlayer](#dismissfullscreenplayer)|Android, iOS| +|[presentFullscreenPlayer](#presentfullscreenplayer)|Android, iOS| |[save](#save)|iOS| |[restoreUserInterfaceForPictureInPictureStop](#restoreuserinterfaceforpictureinpicturestop)|iOS| |[seek](#seek)|All| @@ -409,7 +401,7 @@ Platforms: iOS #### backBufferDurationMs The number of milliseconds of buffer to keep before the current position. This allows rewinding without rebuffering within that duration. -Platforms: Android ExoPlayer +Platforms: Android #### bufferConfig Adjust the buffer settings. This prop takes an object with one or more of the properties listed below. @@ -436,12 +428,12 @@ bufferConfig={{ }} ``` -Platforms: Android ExoPlayer +Platforms: Android #### currentPlaybackTime When playing an HLS live stream with a `EXT-X-PROGRAM-DATE-TIME` tag configured, then this property will contain the epoch value in msec. -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### controls Determines whether to show player controls. @@ -453,30 +445,28 @@ Note on iOS, controls are always shown when in fullscreen mode. ### contentStartTime The start time in ms for SSAI content. This determines at what time to load the video info like resolutions. Use this only when you have SSAI stream where ads resolution is not the same as content resolution. -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, native controls are available by default. If needed, you can also add your controls or use a package like [react-native-video-controls]. -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 +Platforms: Android, iOS, react-native-dom #### disableFocus Determines whether video audio should override background music/audio in Android devices. * ** false (default)** - Override background audio/music * **true** - Let background audio/music from other apps play -Platforms: Android Exoplayer +Platforms: Android #### disableDisconnectError Determines if the player needs to throw an error when connection is lost or not * **false (default)** - Player will throw an error when connection is lost * **true** - Player will keep trying to buffer when network connect is lost -Platforms: Android Exoplayer +Platforms: Android ### DRM To setup DRM please follow [this guide](./DRM.md) -Platforms: Android Exoplayer, iOS +Platforms: Android, iOS #### filter Add video filter @@ -548,7 +538,7 @@ source={{ }} ``` -Platforms: Android ExoPlayer +Platforms: Android #### hideShutterView Controls whether the ExoPlayer shutter view (black screen while loading) is enabled. @@ -556,7 +546,7 @@ Controls whether the ExoPlayer shutter view (black screen while loading) is enab * **false (default)** - Show shutter view * **true** - Hide shutter view -Platforms: Android ExoPlayer +Platforms: Android #### id Set the DOM id element so you can use document.getElementById on web platforms. Accepts string values. @@ -586,7 +576,7 @@ Example: maxBitRate={2000000} // 2 megabits ``` -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### minLoadRetryCount Sets the minimum number of times to retry loading data before failing and reporting an error to the application. Useful to recover from transient internet failures. @@ -598,7 +588,7 @@ Example: minLoadRetryCount={5} // retry 5 times ``` -Platforms: Android ExoPlayer +Platforms: Android #### mixWithOthers Controls how Audio mix with other apps. @@ -638,7 +628,7 @@ To use this feature on iOS, you must: * [Enable Background Audio](https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionBasics/AudioSessionBasics.html#//apple_ref/doc/uid/TP40007875-CH3-SW3) in your Xcode project * Set the ignoreSilentSwitch prop to "ignore" -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### playWhenInactive Determine whether the media should continue playing when notifications or the Control Center are in front of the video. @@ -693,8 +683,6 @@ Speed at which the media should play. Platforms: all -Note: For Android MediaPlayer, rate is only supported on Android 6.0 and higher devices. - #### repeat Determine whether to repeat the video when the end is reached * **false (default)** - Don't repeat the video @@ -708,7 +696,7 @@ Determine whether to generate onBandwidthUpdate events. This is needed due to th * **false (default)** - Don't generate onBandwidthUpdate events * **true** - Generate onBandwidthUpdate events -Platforms: Android ExoPlayer +Platforms: Android #### resizeMode Determines how to resize the video when the frame doesn't match the raw video dimensions. @@ -717,7 +705,7 @@ Determines how to resize the video when the frame doesn't match the raw video di * **"cover"** - Scale the video uniformly (maintain the video's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding). * **"stretch"** - Scale width and height independently, This may change the aspect ratio of the src. -Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Windows UWP +Platforms: Android, iOS, Windows UWP #### selectedAudioTrack Configure which audio track, if any, is played. @@ -747,7 +735,7 @@ Type | Value | Description If a track matching the specified Type (and Value if appropriate) is unavailable, the first audio track will be played. If multiple tracks match the criteria, the first match will be used. -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### selectedTextTrack Configure which text track (caption or subtitle), if any, is shown. @@ -779,7 +767,7 @@ Both iOS & Android (only 4.4 and higher) offer Settings to enable Captions for h If a track matching the specified Type (and Value if appropriate) is unavailable, no text track will be displayed. If multiple tracks match the criteria, the first match will be used. -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### selectedVideoTrack Configure which video track should be played. By default, the player uses Adaptive Bitrate Streaming to automatically select the stream it thinks will perform best based on available bandwidth. @@ -808,7 +796,7 @@ Type | Value | Description If a track matching the specified Type (and Value if appropriate) is unavailable, ABR will be used. -Platforms: Android ExoPlayer +Platforms: Android #### source Sets the media source. You can pass an asset loaded via require or an object with a uri. @@ -853,7 +841,7 @@ source={{ uri: 'file:///sdcard/Movies/sintel.mp4' }} Note: Your app will need to request permission to read external storage if you're accessing a file outside your app. -Platforms: Android ExoPlayer, Android MediaPlayer, possibly others +Platforms: Android, possibly others ###### iPod Library (ipod-library://) @@ -885,14 +873,6 @@ The following other types are supported on some platforms, but aren't fully docu `content://, ms-appx://, ms-appdata://, assets-library://` -#### stereoPan -Adjust the balance of the left and right audio channels. Any value between –1.0 and 1.0 is accepted. -* **-1.0** - Full left -* **0.0 (default)** - Center -* **1.0** - Full right - -Platforms: Android MediaPlayer - #### textTracks Load one or more "sidecar" text tracks. This takes an array of objects representing each track. Each object should have the format: @@ -900,7 +880,7 @@ Property | Description --- | --- title | Descriptive name for the track language | 2 letter [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) representing the language -type | Mime type of the track
* TextTrackType.SRT - SubRip (.srt)
* TextTrackType.TTML - TTML (.ttml)
* TextTrackType.VTT - WebVTT (.vtt)
iOS only supports VTT, Android ExoPlayer supports all 3 +type | Mime type of the track
* TextTrackType.SRT - SubRip (.srt)
* TextTrackType.TTML - TTML (.ttml)
* TextTrackType.VTT - WebVTT (.vtt)
iOS only supports VTT, Android supports all 3 uri | URL for the text track. Currently, only tracks hosted on a webserver are supported On iOS, sidecar text tracks are only supported for individual files, not HLS playlists. For HLS, you should include the text tracks as part of the playlist. @@ -928,12 +908,12 @@ textTracks={[ ``` -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### trackId Configure an identifier for the video stream to link the playback context to the events emitted. -Platforms: Android ExoPlayer +Platforms: Android #### useTextureView Controls whether to output to a TextureView or SurfaceView. @@ -947,7 +927,7 @@ useTextureView can only be set at same time you're setting the source. * **true (default)** - Use a TextureView * **false** - Use a SurfaceView -Platforms: Android ExoPlayer +Platforms: Android #### useSecureView Force the output to a SurfaceView and enables the secure surface. @@ -959,7 +939,7 @@ SurfaceView is is the only one that can be labeled as secure. * **true** - Use security * **false (default)** - Do not use security -Platforms: Android ExoPlayer +Platforms: Android #### volume Adjust the volume. @@ -989,7 +969,7 @@ Callback function that is called when the audio is about to become 'noisy' due t Payload: none -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### onBandwidthUpdate Callback function that is called when the available bandwidth changes. @@ -1007,9 +987,9 @@ Example: } ``` -Note: On Android ExoPlayer, you must set the [reportBandwidth](#reportbandwidth) prop to enable this event. This is due to the high volume of events generated. +Note: On Android, you must set the [reportBandwidth](#reportbandwidth) prop to enable this event. This is due to the high volume of events generated. -Platforms: Android ExoPlayer +Platforms: Android #### onBuffer Callback function that is called when the player buffers. @@ -1027,7 +1007,7 @@ Example: } ``` -Platforms: Android ExoPlayer, iOS +Platforms: Android, iOS #### onEnd Callback function that is called when the player reaches the end of the media. @@ -1059,28 +1039,28 @@ Callback function that is called when the player is about to enter fullscreen mo Payload: none -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### onFullscreenPlayerDidPresent Callback function that is called when the player has entered fullscreen mode. Payload: none -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### onFullscreenPlayerWillDismiss Callback function that is called when the player is about to exit fullscreen mode. Payload: none -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### onFullscreenPlayerDidDismiss Callback function that is called when the player has exited fullscreen mode. Payload: none -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### onLoad Callback function that is called when the media is loaded and ready to play. @@ -1169,7 +1149,7 @@ Example: } ``` -Platforms: Android ExoPlayer +Platforms: Android #### onReadyForDisplay Callback function that is called when the first video frame is ready for display. This is when the poster is removed. @@ -1177,10 +1157,9 @@ Callback function that is called when the first video frame is ready for display Payload: none * iOS: [readyForDisplay](https://developer.apple.com/documentation/avkit/avplayerviewcontroller/1615830-readyfordisplay?language=objc) -* Android: [MEDIA_INFO_VIDEO_RENDERING_START](https://developer.android.com/reference/android/media/MediaPlayer#MEDIA_INFO_VIDEO_RENDERING_START) -* Android ExoPlayer [STATE_READY](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#STATE_READY) +* Android [STATE_READY](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#STATE_READY) -Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Web +Platforms: Android, iOS, Web #### onPictureInPictureStatusChanged Callback function that is called when picture in picture becomes active or inactive. @@ -1256,7 +1235,7 @@ Example: Both the currentTime & seekTime are reported because the video player may not seek to the exact requested position in order to improve seek performance. -Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Windows UWP +Platforms: Android, iOS, Windows UWP #### onRestoreUserInterfaceForPictureInPictureStop Callback function that corresponds to Apple's [`restoreUserInterfaceForPictureInPictureStopWithCompletionHandler`](https://developer.apple.com/documentation/avkit/avpictureinpicturecontrollerdelegate/1614703-pictureinpicturecontroller?language=objc). Call `restoreUserInterfaceForPictureInPictureStopCompleted` inside of this function when done restoring the user interface. @@ -1285,9 +1264,7 @@ Example: } ``` -Support for timed metadata on Android MediaPlayer is limited at best and only compatible with some videos. It requires a target SDK of 23 or higher. - -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS ### Methods Methods operate on a ref to the Video element. You can create a ref using code like: @@ -1308,7 +1285,7 @@ Example: this.player.dismissFullscreenPlayer(); ``` -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### presentFullscreenPlayer `presentFullscreenPlayer()` @@ -1317,14 +1294,14 @@ Put the player in fullscreen mode. On iOS, this displays the video in a fullscreen view controller with controls. -On Android ExoPlayer & MediaPlayer, this puts the navigation controls in fullscreen mode. It is not a complete fullscreen implementation, so you will still need to apply a style that makes the width and height match your screen dimensions to get a fullscreen video. +On Android, this puts the navigation controls in fullscreen mode. It is not a complete fullscreen implementation, so you will still need to apply a style that makes the width and height match your screen dimensions to get a fullscreen video. Example: ``` this.player.presentFullscreenPlayer(); ``` -Platforms: Android ExoPlayer, Android MediaPlayer, iOS +Platforms: Android, iOS #### save `save(): Promise` @@ -1539,7 +1516,7 @@ android { ``` #### ExoPlayer no longer detaches -When using a router like the react-navigation TabNavigator, switching between tab routes would previously cause ExoPlayer to detach causing the video player to pause. We now don't detach the view, allowing the video to continue playing in a background tab. This matches the behavior for iOS. Android MediaPlayer will crash if it detaches when switching routes, so its behavior has not been changed. +When using a router like the react-navigation TabNavigator, switching between tab routes would previously cause ExoPlayer to detach causing the video player to pause. We now don't detach the view, allowing the video to continue playing in a background tab. This matches the behavior for iOS. #### useTextureView now defaults to true The SurfaceView, which ExoPlayer has been using by default has a number of quirks that people are unaware of and often cause issues. This includes not supporting animations or scaling. It also causes strange behavior if you overlay two videos on top of each other, because the SurfaceView will [punch a hole](https://developer.android.com/reference/android/view/SurfaceView) through other views. Since TextureView doesn't have these issues and behaves in the way most developers expect, it makes sense to make it the default. diff --git a/CHANGELOG.md b/CHANGELOG.md index d71097a1..a7a90a53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ ## Changelog -### Version 6.0.0-alpha.1 +### Version 6.0.0-alpha1 +- Remove Android MediaPlayer support [#2724](https://github.com/react-native-video/react-native-video/pull/2724) - Replace Image.propTypes with ImagePropTypes. [#2718](https://github.com/react-native-video/react-native-video/pull/2718) -- + ### Version 6.0.0-alpha.0 - Support disabling buffering [#2689](https://github.com/react-native-video/react-native-video/pull/2689) - Fix AudioFocus bug that could cause the player to stop responding to play/pause in some instances. [#2689](https://github.com/react-native-video/react-native-video/pull/2689) diff --git a/Video.js b/Video.js index d398763a..dad262b9 100644 --- a/Video.js +++ b/Video.js @@ -473,7 +473,6 @@ Video.propTypes = { bufferForPlaybackAfterRebufferMs: PropTypes.number, maxHeapAllocationPercent: PropTypes.number, }), - stereoPan: PropTypes.number, rate: PropTypes.number, pictureInPicture: PropTypes.bool, playInBackground: PropTypes.bool, diff --git a/android-exoplayer/build.gradle b/android-exoplayer/build.gradle deleted file mode 100644 index a93e7599..00000000 --- a/android-exoplayer/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -apply plugin: 'com.android.library' - -def safeExtGet(prop, fallback) { - rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback -} - -android { - compileSdkVersion safeExtGet('compileSdkVersion', 31) - buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2') - - compileOptions { - targetCompatibility JavaVersion.VERSION_1_8 - sourceCompatibility JavaVersion.VERSION_1_8 - } - - defaultConfig { - minSdkVersion safeExtGet('minSdkVersion', 21) - targetSdkVersion safeExtGet('targetSdkVersion', 28) - versionCode 1 - versionName "1.0" - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } -} - -repositories { - // Remove this repository line after google releases to google() or mavenCentral() - maven { url "https://dl.google.com/android/maven2" } -} - -dependencies { - implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" - implementation('com.google.android.exoplayer:exoplayer:2.17.1') { - exclude group: 'com.android.support' - } - - // All support libs must use the same version - implementation "androidx.annotation:annotation:1.1.0" - implementation "androidx.core:core:1.1.0" - implementation "androidx.media:media:1.1.0" - - implementation('com.google.android.exoplayer:extension-okhttp:2.17.1') { - exclude group: 'com.squareup.okhttp3', module: 'okhttp' - } - implementation 'com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}' - -} diff --git a/android-exoplayer/src/main/AndroidManifest.xml b/android-exoplayer/src/main/AndroidManifest.xml deleted file mode 100644 index 3535ad44..00000000 --- a/android-exoplayer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/android-exoplayer/src/main/java/com/brentvatne/react/ReactVideoPackage.java b/android-exoplayer/src/main/java/com/brentvatne/react/ReactVideoPackage.java deleted file mode 100644 index f7a5d02a..00000000 --- a/android-exoplayer/src/main/java/com/brentvatne/react/ReactVideoPackage.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.brentvatne.react; - -import com.brentvatne.exoplayer.DefaultReactExoplayerConfig; -import com.brentvatne.exoplayer.ReactExoplayerConfig; -import com.brentvatne.exoplayer.ReactExoplayerViewManager; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.Collections; -import java.util.List; - -public class ReactVideoPackage implements ReactPackage { - - private ReactExoplayerConfig config; - - public ReactVideoPackage() { - } - - public ReactVideoPackage(ReactExoplayerConfig config) { - this.config = config; - } - - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } - - // Deprecated RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); - } - - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - if (config == null) { - config = new DefaultReactExoplayerConfig(reactContext); - } - return Collections.singletonList(new ReactExoplayerViewManager(config)); - } -} diff --git a/android-exoplayer/README.md b/android/README.md similarity index 100% rename from android-exoplayer/README.md rename to android/README.md diff --git a/android/build.gradle b/android/build.gradle index b382a85f..a93e7599 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,19 +8,43 @@ android { compileSdkVersion safeExtGet('compileSdkVersion', 31) buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2') + compileOptions { + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 + } + defaultConfig { minSdkVersion safeExtGet('minSdkVersion', 21) targetSdkVersion safeExtGet('targetSdkVersion', 28) versionCode 1 versionName "1.0" - ndk { - abiFilters "armeabi-v7a", "x86" - } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } } -dependencies { - //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" - implementation 'com.github.thang2162:Android-ScalableVideoView:v1.1.1' +repositories { + // Remove this repository line after google releases to google() or mavenCentral() + maven { url "https://dl.google.com/android/maven2" } +} + +dependencies { + implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" + implementation('com.google.android.exoplayer:exoplayer:2.17.1') { + exclude group: 'com.android.support' + } + + // All support libs must use the same version + implementation "androidx.annotation:annotation:1.1.0" + implementation "androidx.core:core:1.1.0" + implementation "androidx.media:media:1.1.0" + + implementation('com.google.android.exoplayer:extension-okhttp:2.17.1') { + exclude group: 'com.squareup.okhttp3', module: 'okhttp' + } + implementation 'com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}' + } diff --git a/android/src/main/java/com/android/vending/expansion/zipfile/APEZProvider.java b/android/src/main/java/com/android/vending/expansion/zipfile/APEZProvider.java deleted file mode 100644 index 1ba910bf..00000000 --- a/android/src/main/java/com/android/vending/expansion/zipfile/APEZProvider.java +++ /dev/null @@ -1,287 +0,0 @@ -package com.android.vending.expansion.zipfile; - -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//To implement APEZProvider in your application, you'll want to change -//the AUTHORITY to match what you define in the manifest. - -import com.android.vending.expansion.zipfile.ZipResourceFile.ZipEntryRO; - -import android.content.ContentProvider; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentValues; -import android.content.Context; -import android.content.OperationApplicationException; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ProviderInfo; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.provider.BaseColumns; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; - -/** - * This content provider is an optional part of the library. - * - *

Most apps don't need to use this class. This defines a - * ContentProvider that marshalls the data from the ZIP files through a - * content provider Uri in order to provide file access for certain Android APIs - * that expect Uri access to media files. - * - */ -public abstract class APEZProvider extends ContentProvider { - - private ZipResourceFile mAPKExtensionFile; - private boolean mInit; - - public static final String FILEID = BaseColumns._ID; - public static final String FILENAME = "ZPFN"; - public static final String ZIPFILE = "ZFIL"; - public static final String MODIFICATION = "ZMOD"; - public static final String CRC32 = "ZCRC"; - public static final String COMPRESSEDLEN = "ZCOL"; - public static final String UNCOMPRESSEDLEN = "ZUNL"; - public static final String COMPRESSIONTYPE = "ZTYP"; - - public static final String[] ALL_FIELDS = { - FILEID, - FILENAME, - ZIPFILE, - MODIFICATION, - CRC32, - COMPRESSEDLEN, - UNCOMPRESSEDLEN, - COMPRESSIONTYPE - }; - - public static final int FILEID_IDX = 0; - public static final int FILENAME_IDX = 1; - public static final int ZIPFILE_IDX = 2; - public static final int MOD_IDX = 3; - public static final int CRC_IDX = 4; - public static final int COMPLEN_IDX = 5; - public static final int UNCOMPLEN_IDX = 6; - public static final int COMPTYPE_IDX = 7; - - public static final int[] ALL_FIELDS_INT = { - FILEID_IDX, - FILENAME_IDX, - ZIPFILE_IDX, - MOD_IDX, - CRC_IDX, - COMPLEN_IDX, - UNCOMPLEN_IDX, - COMPTYPE_IDX - }; - - /** - * This needs to match the authority in your manifest - */ - public abstract String getAuthority(); - - @Override - public int delete(Uri arg0, String arg1, String[] arg2) { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getType(Uri uri) { - return "vnd.android.cursor.item/asset"; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - // TODO Auto-generated method stub - return null; - } - - static private final String NO_FILE = "N"; - - private boolean initIfNecessary() { - if ( !mInit ) { - Context ctx = getContext(); - PackageManager pm = ctx.getPackageManager(); - ProviderInfo pi = pm.resolveContentProvider(getAuthority(), PackageManager.GET_META_DATA); - PackageInfo packInfo; - try { - packInfo = pm.getPackageInfo(ctx.getPackageName(), 0); - } catch (NameNotFoundException e1) { - e1.printStackTrace(); - return false; - } - int patchFileVersion; - int mainFileVersion; - int appVersionCode = packInfo.versionCode; - String[] resourceFiles = null; - if ( null != pi.metaData ) { - mainFileVersion = pi.metaData.getInt("mainVersion", appVersionCode); - patchFileVersion = pi.metaData.getInt("patchVersion", appVersionCode); - String mainFileName = pi.metaData.getString("mainFilename", NO_FILE); - if ( NO_FILE != mainFileName ) { - String patchFileName = pi.metaData.getString("patchFilename", NO_FILE); - if ( NO_FILE != patchFileName ) { - resourceFiles = new String[] { mainFileName, patchFileName }; - } else { - resourceFiles = new String[] { mainFileName }; - } - } - } else { - mainFileVersion = patchFileVersion = appVersionCode; - } - try { - if ( null == resourceFiles ) { - mAPKExtensionFile = APKExpansionSupport.getAPKExpansionZipFile(ctx, mainFileVersion, patchFileVersion); - } else { - mAPKExtensionFile = APKExpansionSupport.getResourceZipFile(resourceFiles); - } - mInit = true; - return true; - } catch (IOException e) { - e.printStackTrace(); - } - } - return false; - } - - @Override - public boolean onCreate() { - return true; - } - - @Override - public AssetFileDescriptor openAssetFile(Uri uri, String mode) - throws FileNotFoundException { - initIfNecessary(); - String path = uri.getEncodedPath(); - if ( path.startsWith("/") ) { - path = path.substring(1); - } - return mAPKExtensionFile.getAssetFileDescriptor(path); - } - - @Override - public ContentProviderResult[] applyBatch( - ArrayList operations) - throws OperationApplicationException { - initIfNecessary(); - return super.applyBatch(operations); - } - - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - initIfNecessary(); - AssetFileDescriptor af = openAssetFile(uri, mode); - if ( null != af ) { - return af.getParcelFileDescriptor(); - } - return null; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { - initIfNecessary(); - // lists all of the items in the file that match - ZipEntryRO[] zipEntries; - if ( null == mAPKExtensionFile ) { - zipEntries = new ZipEntryRO[0]; - } else { - zipEntries = mAPKExtensionFile.getAllEntries(); - } - int[] intProjection; - if ( null == projection ) { - intProjection = ALL_FIELDS_INT; - projection = ALL_FIELDS; - } else { - int len = projection.length; - intProjection = new int[len]; - for ( int i = 0; i < len; i++ ) { - if ( projection[i].equals(FILEID) ) { - intProjection[i] = FILEID_IDX; - } else if ( projection[i].equals(FILENAME) ) { - intProjection[i] = FILENAME_IDX; - } else if ( projection[i].equals(ZIPFILE) ) { - intProjection[i] = ZIPFILE_IDX; - } else if ( projection[i].equals(MODIFICATION) ) { - intProjection[i] = MOD_IDX; - } else if ( projection[i].equals(CRC32) ) { - intProjection[i] = CRC_IDX; - } else if ( projection[i].equals(COMPRESSEDLEN) ) { - intProjection[i] = COMPLEN_IDX; - } else if ( projection[i].equals(UNCOMPRESSEDLEN) ) { - intProjection[i] = UNCOMPLEN_IDX; - } else if ( projection[i].equals(COMPRESSIONTYPE) ) { - intProjection[i] = COMPTYPE_IDX; - } else { - throw new RuntimeException(); - } - } - } - MatrixCursor mc = new MatrixCursor(projection, zipEntries.length); - int len = intProjection.length; - for ( ZipEntryRO zer : zipEntries ) { - MatrixCursor.RowBuilder rb = mc.newRow(); - for ( int i = 0; i < len; i++ ) { - switch (intProjection[i]) { - case FILEID_IDX: - rb.add(i); - break; - case FILENAME_IDX: - rb.add(zer.mFileName); - break; - case ZIPFILE_IDX: - rb.add(zer.getZipFileName()); - break; - case MOD_IDX: - rb.add(zer.mWhenModified); - break; - case CRC_IDX: - rb.add(zer.mCRC32); - break; - case COMPLEN_IDX: - rb.add(zer.mCompressedLength); - break; - case UNCOMPLEN_IDX: - rb.add(zer.mUncompressedLength); - break; - case COMPTYPE_IDX: - rb.add(zer.mMethod); - break; - } - } - } - return mc; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, - String[] selectionArgs) { - // TODO Auto-generated method stub - return 0; - } - -} diff --git a/android/src/main/java/com/android/vending/expansion/zipfile/APKExpansionSupport.java b/android/src/main/java/com/android/vending/expansion/zipfile/APKExpansionSupport.java deleted file mode 100644 index 34669c1d..00000000 --- a/android/src/main/java/com/android/vending/expansion/zipfile/APKExpansionSupport.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.android.vending.expansion.zipfile; -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.Vector; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import android.content.Context; -import android.os.Environment; -import android.util.Log; - -public class APKExpansionSupport { - // The shared path to all app expansion files - private final static String EXP_PATH = "/Android/obb/"; - - static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) { - String packageName = ctx.getPackageName(); - Vector ret = new Vector(); - if (Environment.getExternalStorageState().equals( - Environment.MEDIA_MOUNTED)) { - // Build the full path to the app's expansion files - File root = Environment.getExternalStorageDirectory(); - File expPath = new File(root.toString() + EXP_PATH + packageName); - - // Check that expansion file path exists - if (expPath.exists()) { - if ( mainVersion > 0 ) { - String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb"; -// Log.d("APKEXPANSION", strMainPath); - File main = new File(strMainPath); - if ( main.isFile() ) { - ret.add(strMainPath); - } - } - if ( patchVersion > 0 ) { - String strPatchPath = expPath + File.separator + "patch." + patchVersion + "." + packageName + ".obb"; - File main = new File(strPatchPath); - if ( main.isFile() ) { - ret.add(strPatchPath); - } - } - } - } - String[] retArray = new String[ret.size()]; - ret.toArray(retArray); - return retArray; - } - - static public ZipResourceFile getResourceZipFile(String[] expansionFiles) throws IOException { - ZipResourceFile apkExpansionFile = null; - for (String expansionFilePath : expansionFiles) { - if ( null == apkExpansionFile ) { - apkExpansionFile = new ZipResourceFile(expansionFilePath); - } else { - apkExpansionFile.addPatchFile(expansionFilePath); - } - } - return apkExpansionFile; - } - - static public ZipResourceFile getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion) throws IOException{ - String[] expansionFiles = getAPKExpansionFiles(ctx, mainVersion, patchVersion); - return getResourceZipFile(expansionFiles); - } -} diff --git a/android/src/main/java/com/android/vending/expansion/zipfile/ZipResourceFile.java b/android/src/main/java/com/android/vending/expansion/zipfile/ZipResourceFile.java deleted file mode 100644 index 902af3c4..00000000 --- a/android/src/main/java/com/android/vending/expansion/zipfile/ZipResourceFile.java +++ /dev/null @@ -1,428 +0,0 @@ - -package com.android.vending.expansion.zipfile; - -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import android.content.res.AssetFileDescriptor; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import java.io.EOFException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.util.Collection; -import java.util.HashMap; -import java.util.Vector; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -public class ZipResourceFile { - - // - // Read-only access to Zip archives, with minimal heap allocation. - // - static final String LOG_TAG = "zipro"; - static final boolean LOGV = false; - - // 4-byte number - static private int swapEndian(int i) - { - return ((i & 0xff) << 24) + ((i & 0xff00) << 8) + ((i & 0xff0000) >>> 8) - + ((i >>> 24) & 0xff); - } - - // 2-byte number - static private int swapEndian(short i) - { - return ((i & 0x00FF) << 8 | (i & 0xFF00) >>> 8); - } - - /* - * Zip file constants. - */ - static final int kEOCDSignature = 0x06054b50; - static final int kEOCDLen = 22; - static final int kEOCDNumEntries = 8; // offset to #of entries in file - static final int kEOCDSize = 12; // size of the central directory - static final int kEOCDFileOffset = 16; // offset to central directory - - static final int kMaxCommentLen = 65535; // longest possible in ushort - static final int kMaxEOCDSearch = (kMaxCommentLen + kEOCDLen); - - static final int kLFHSignature = 0x04034b50; - static final int kLFHLen = 30; // excluding variable-len fields - static final int kLFHNameLen = 26; // offset to filename length - static final int kLFHExtraLen = 28; // offset to extra length - - static final int kCDESignature = 0x02014b50; - static final int kCDELen = 46; // excluding variable-len fields - static final int kCDEMethod = 10; // offset to compression method - static final int kCDEModWhen = 12; // offset to modification timestamp - static final int kCDECRC = 16; // offset to entry CRC - static final int kCDECompLen = 20; // offset to compressed length - static final int kCDEUncompLen = 24; // offset to uncompressed length - static final int kCDENameLen = 28; // offset to filename length - static final int kCDEExtraLen = 30; // offset to extra length - static final int kCDECommentLen = 32; // offset to comment length - static final int kCDELocalOffset = 42; // offset to local hdr - - static final int kCompressStored = 0; // no compression - static final int kCompressDeflated = 8; // standard deflate - - /* - * The values we return for ZipEntryRO use 0 as an invalid value, so we want - * to adjust the hash table index by a fixed amount. Using a large value - * helps insure that people don't mix & match arguments, e.g. to - * findEntryByIndex(). - */ - static final int kZipEntryAdj = 10000; - - static public final class ZipEntryRO { - public ZipEntryRO(final String zipFileName, final File file, final String fileName) { - mFileName = fileName; - mZipFileName = zipFileName; - mFile = file; - } - - public final File mFile; - public final String mFileName; - public final String mZipFileName; - public long mLocalHdrOffset; // offset of local file header - - /* useful stuff from the directory entry */ - public int mMethod; - public long mWhenModified; - public long mCRC32; - public long mCompressedLength; - public long mUncompressedLength; - - public long mOffset = -1; - - public void setOffsetFromFile(RandomAccessFile f, ByteBuffer buf) throws IOException { - long localHdrOffset = mLocalHdrOffset; - try { - f.seek(localHdrOffset); - f.readFully(buf.array()); - if (buf.getInt(0) != kLFHSignature) { - Log.w(LOG_TAG, "didn't find signature at start of lfh"); - throw new IOException(); - } - int nameLen = buf.getShort(kLFHNameLen) & 0xFFFF; - int extraLen = buf.getShort(kLFHExtraLen) & 0xFFFF; - mOffset = localHdrOffset + kLFHLen + nameLen + extraLen; - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - /** - * Calculates the offset of the start of the Zip file entry within the - * Zip file. - * - * @return the offset, in bytes from the start of the file of the entry - */ - public long getOffset() { - return mOffset; - } - - /** - * isUncompressed - * - * @return true if the file is stored in uncompressed form - */ - public boolean isUncompressed() { - return mMethod == kCompressStored; - } - - public AssetFileDescriptor getAssetFileDescriptor() { - if (mMethod == kCompressStored) { - ParcelFileDescriptor pfd; - try { - pfd = ParcelFileDescriptor.open(mFile, ParcelFileDescriptor.MODE_READ_ONLY); - return new AssetFileDescriptor(pfd, getOffset(), mUncompressedLength); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return null; - } - - public String getZipFileName() { - return mZipFileName; - } - - public File getZipFile() { - return mFile; - } - - } - - private HashMap mHashMap = new HashMap(); - - /* for reading compressed files */ - public HashMap mZipFiles = new HashMap(); - - public ZipResourceFile(String zipFileName) throws IOException { - addPatchFile(zipFileName); - } - - ZipEntryRO[] getEntriesAt(String path) { - Vector zev = new Vector(); - Collection values = mHashMap.values(); - if (null == path) - path = ""; - int length = path.length(); - for (ZipEntryRO ze : values) { - if (ze.mFileName.startsWith(path)) { - if (-1 == ze.mFileName.indexOf('/', length)) { - zev.add(ze); - } - } - } - ZipEntryRO[] entries = new ZipEntryRO[zev.size()]; - return zev.toArray(entries); - } - - public ZipEntryRO[] getAllEntries() { - Collection values = mHashMap.values(); - return values.toArray(new ZipEntryRO[values.size()]); - } - - /** - * getAssetFileDescriptor allows for ZipResourceFile to directly feed - * Android API's that want an fd, offset, and length such as the - * MediaPlayer. It also allows for the class to be used in a content - * provider that can feed video players. The file must be stored - * (non-compressed) in the Zip file for this to work. - * - * @param assetPath - * @return the asset file descriptor for the file, or null if the file isn't - * present or is stored compressed - */ - public AssetFileDescriptor getAssetFileDescriptor(String assetPath) { - ZipEntryRO entry = mHashMap.get(assetPath); - if (null != entry) { - return entry.getAssetFileDescriptor(); - } - return null; - } - - /** - * getInputStream returns an AssetFileDescriptor.AutoCloseInputStream - * associated with the asset that is contained in the Zip file, or a - * standard ZipInputStream if necessary to uncompress the file - * - * @param assetPath - * @return an input stream for the named asset path, or null if not found - * @throws IOException - */ - public InputStream getInputStream(String assetPath) throws IOException { - ZipEntryRO entry = mHashMap.get(assetPath); - if (null != entry) { - if (entry.isUncompressed()) { - return entry.getAssetFileDescriptor().createInputStream(); - } else { - ZipFile zf = mZipFiles.get(entry.getZipFile()); - /** read compressed files **/ - if (null == zf) { - zf = new ZipFile(entry.getZipFile(), ZipFile.OPEN_READ); - mZipFiles.put(entry.getZipFile(), zf); - } - ZipEntry zi = zf.getEntry(assetPath); - if (null != zi) - return zf.getInputStream(zi); - } - } - return null; - } - - ByteBuffer mLEByteBuffer = ByteBuffer.allocate(4); - - static private int read4LE(RandomAccessFile f) throws EOFException, IOException { - return swapEndian(f.readInt()); - } - - /* - * Opens the specified file read-only. We memory-map the entire thing and - * close the file before returning. - */ - void addPatchFile(String zipFileName) throws IOException - { - File file = new File(zipFileName); - RandomAccessFile f = new RandomAccessFile(file, "r"); - long fileLength = f.length(); - - if (fileLength < kEOCDLen) { - throw new java.io.IOException(); - } - - long readAmount = kMaxEOCDSearch; - if (readAmount > fileLength) - readAmount = fileLength; - - /* - * Make sure this is a Zip archive. - */ - f.seek(0); - - int header = read4LE(f); - if (header == kEOCDSignature) { - Log.i(LOG_TAG, "Found Zip archive, but it looks empty"); - throw new IOException(); - } else if (header != kLFHSignature) { - Log.v(LOG_TAG, "Not a Zip archive"); - throw new IOException(); - } - - /* - * Perform the traditional EOCD snipe hunt. We're searching for the End - * of Central Directory magic number, which appears at the start of the - * EOCD block. It's followed by 18 bytes of EOCD stuff and up to 64KB of - * archive comment. We need to read the last part of the file into a - * buffer, dig through it to find the magic number, parse some values - * out, and use those to determine the extent of the CD. We start by - * pulling in the last part of the file. - */ - long searchStart = fileLength - readAmount; - - f.seek(searchStart); - ByteBuffer bbuf = ByteBuffer.allocate((int) readAmount); - byte[] buffer = bbuf.array(); - f.readFully(buffer); - bbuf.order(ByteOrder.LITTLE_ENDIAN); - - /* - * Scan backward for the EOCD magic. In an archive without a trailing - * comment, we'll find it on the first try. (We may want to consider - * doing an initial minimal read; if we don't find it, retry with a - * second read as above.) - */ - - // EOCD == 0x50, 0x4b, 0x05, 0x06 - int eocdIdx; - for (eocdIdx = buffer.length - kEOCDLen; eocdIdx >= 0; eocdIdx--) { - if (buffer[eocdIdx] == 0x50 && bbuf.getInt(eocdIdx) == kEOCDSignature) - { - if (LOGV) { - Log.v(LOG_TAG, "+++ Found EOCD at index: " + eocdIdx); - } - break; - } - } - - if (eocdIdx < 0) { - Log.d(LOG_TAG, "Zip: EOCD not found, " + zipFileName + " is not zip"); - } - - /* - * Grab the CD offset and size, and the number of entries in the - * archive. After that, we can release our EOCD hunt buffer. - */ - - int numEntries = bbuf.getShort(eocdIdx + kEOCDNumEntries); - long dirSize = bbuf.getInt(eocdIdx + kEOCDSize) & 0xffffffffL; - long dirOffset = bbuf.getInt(eocdIdx + kEOCDFileOffset) & 0xffffffffL; - - // Verify that they look reasonable. - if (dirOffset + dirSize > fileLength) { - Log.w(LOG_TAG, "bad offsets (dir " + dirOffset + ", size " + dirSize + ", eocd " - + eocdIdx + ")"); - throw new IOException(); - } - if (numEntries == 0) { - Log.w(LOG_TAG, "empty archive?"); - throw new IOException(); - } - - if (LOGV) { - Log.v(LOG_TAG, "+++ numEntries=" + numEntries + " dirSize=" + dirSize + " dirOffset=" - + dirOffset); - } - - MappedByteBuffer directoryMap = f.getChannel() - .map(FileChannel.MapMode.READ_ONLY, dirOffset, dirSize); - directoryMap.order(ByteOrder.LITTLE_ENDIAN); - - byte[] tempBuf = new byte[0xffff]; - - /* - * Walk through the central directory, adding entries to the hash table. - */ - - int currentOffset = 0; - - /* - * Allocate the local directory information - */ - ByteBuffer buf = ByteBuffer.allocate(kLFHLen); - buf.order(ByteOrder.LITTLE_ENDIAN); - - for (int i = 0; i < numEntries; i++) { - if (directoryMap.getInt(currentOffset) != kCDESignature) { - Log.w(LOG_TAG, "Missed a central dir sig (at " + currentOffset + ")"); - throw new IOException(); - } - - /* useful stuff from the directory entry */ - int fileNameLen = directoryMap.getShort(currentOffset + kCDENameLen) & 0xffff; - int extraLen = directoryMap.getShort(currentOffset + kCDEExtraLen) & 0xffff; - int commentLen = directoryMap.getShort(currentOffset + kCDECommentLen) & 0xffff; - - /* get the CDE filename */ - - directoryMap.position(currentOffset + kCDELen); - directoryMap.get(tempBuf, 0, fileNameLen); - directoryMap.position(0); - - /* UTF-8 on Android */ - String str = new String(tempBuf, 0, fileNameLen); - if (LOGV) { - Log.v(LOG_TAG, "Filename: " + str); - } - - ZipEntryRO ze = new ZipEntryRO(zipFileName, file, str); - ze.mMethod = directoryMap.getShort(currentOffset + kCDEMethod) & 0xffff; - ze.mWhenModified = directoryMap.getInt(currentOffset + kCDEModWhen) & 0xffffffffL; - ze.mCRC32 = directoryMap.getLong(currentOffset + kCDECRC) & 0xffffffffL; - ze.mCompressedLength = directoryMap.getLong(currentOffset + kCDECompLen) & 0xffffffffL; - ze.mUncompressedLength = directoryMap.getLong(currentOffset + kCDEUncompLen) & 0xffffffffL; - ze.mLocalHdrOffset = directoryMap.getInt(currentOffset + kCDELocalOffset) & 0xffffffffL; - - // set the offsets - buf.clear(); - ze.setOffsetFromFile(f, buf); - - // put file into hash - mHashMap.put(str, ze); - - // go to next directory entry - currentOffset += kCDELen + fileNameLen + extraLen + commentLen; - } - if (LOGV) { - Log.v(LOG_TAG, "+++ zip good scan " + numEntries + " entries"); - } - } -} diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/AspectRatioFrameLayout.java b/android/src/main/java/com/brentvatne/exoplayer/AspectRatioFrameLayout.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/AspectRatioFrameLayout.java rename to android/src/main/java/com/brentvatne/exoplayer/AspectRatioFrameLayout.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java b/android/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java rename to android/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.java b/android/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.java rename to android/src/main/java/com/brentvatne/exoplayer/DefaultReactExoplayerConfig.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java rename to android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/RawResourceDataSourceFactory.java b/android/src/main/java/com/brentvatne/exoplayer/RawResourceDataSourceFactory.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/RawResourceDataSourceFactory.java rename to android/src/main/java/com/brentvatne/exoplayer/RawResourceDataSourceFactory.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.java rename to android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerConfig.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.java rename to android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerLoadErrorHandlingPolicy.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java rename to android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java rename to android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ResizeMode.java b/android/src/main/java/com/brentvatne/exoplayer/ResizeMode.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/ResizeMode.java rename to android/src/main/java/com/brentvatne/exoplayer/ResizeMode.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java b/android/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java rename to android/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java b/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java index b09e9414..f7a5d02a 100644 --- a/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java +++ b/android/src/main/java/com/brentvatne/react/ReactVideoPackage.java @@ -1,18 +1,28 @@ package com.brentvatne.react; -import android.app.Activity; +import com.brentvatne.exoplayer.DefaultReactExoplayerConfig; +import com.brentvatne.exoplayer.ReactExoplayerConfig; +import com.brentvatne.exoplayer.ReactExoplayerViewManager; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; -import java.util.Arrays; import java.util.Collections; import java.util.List; public class ReactVideoPackage implements ReactPackage { + private ReactExoplayerConfig config; + + public ReactVideoPackage() { + } + + public ReactVideoPackage(ReactExoplayerConfig config) { + this.config = config; + } + @Override public List createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); @@ -23,8 +33,12 @@ public class ReactVideoPackage implements ReactPackage { return Collections.emptyList(); } + @Override public List createViewManagers(ReactApplicationContext reactContext) { - return Arrays.asList(new ReactVideoViewManager()); + if (config == null) { + config = new DefaultReactExoplayerConfig(reactContext); + } + return Collections.singletonList(new ReactExoplayerViewManager(config)); } } diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoView.java b/android/src/main/java/com/brentvatne/react/ReactVideoView.java deleted file mode 100644 index 09285fb7..00000000 --- a/android/src/main/java/com/brentvatne/react/ReactVideoView.java +++ /dev/null @@ -1,796 +0,0 @@ -package com.brentvatne.react; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.res.AssetFileDescriptor; -import android.graphics.Matrix; -import android.media.MediaPlayer; -import android.media.TimedMetaData; -import android.net.Uri; -import android.os.Build; -import android.os.Handler; -import android.util.Log; -import android.view.MotionEvent; -import android.view.WindowManager; -import android.view.View; -import android.view.Window; -import android.webkit.CookieManager; -import android.widget.MediaController; - -import com.android.vending.expansion.zipfile.APKExpansionSupport; -import com.android.vending.expansion.zipfile.ZipResourceFile; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableNativeArray; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.events.RCTEventEmitter; -import com.yqritc.scalablevideoview.ScalableType; -import com.yqritc.scalablevideoview.ScalableVideoView; -import com.yqritc.scalablevideoview.ScaleManager; -import com.yqritc.scalablevideoview.Size; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.HashMap; -import java.util.Map; -import java.lang.Math; -import java.math.BigDecimal; - -import javax.annotation.Nullable; - -@SuppressLint("ViewConstructor") -public class ReactVideoView extends ScalableVideoView implements - MediaPlayer.OnPreparedListener, - MediaPlayer.OnErrorListener, - MediaPlayer.OnBufferingUpdateListener, - MediaPlayer.OnSeekCompleteListener, - MediaPlayer.OnCompletionListener, - MediaPlayer.OnInfoListener, - LifecycleEventListener, - MediaController.MediaPlayerControl { - - public enum Events { - EVENT_LOAD_START("onVideoLoadStart"), - EVENT_LOAD("onVideoLoad"), - EVENT_ERROR("onVideoError"), - EVENT_PROGRESS("onVideoProgress"), - EVENT_TIMED_METADATA("onTimedMetadata"), - EVENT_SEEK("onVideoSeek"), - EVENT_END("onVideoEnd"), - EVENT_STALLED("onPlaybackStalled"), - EVENT_RESUME("onPlaybackResume"), - EVENT_READY_FOR_DISPLAY("onReadyForDisplay"), - EVENT_FULLSCREEN_WILL_PRESENT("onVideoFullscreenPlayerWillPresent"), - EVENT_FULLSCREEN_DID_PRESENT("onVideoFullscreenPlayerDidPresent"), - EVENT_FULLSCREEN_WILL_DISMISS("onVideoFullscreenPlayerWillDismiss"), - EVENT_FULLSCREEN_DID_DISMISS("onVideoFullscreenPlayerDidDismiss"); - - private final String mName; - - Events(final String name) { - mName = name; - } - - @Override - public String toString() { - return mName; - } - } - - public static final String EVENT_PROP_FAST_FORWARD = "canPlayFastForward"; - public static final String EVENT_PROP_SLOW_FORWARD = "canPlaySlowForward"; - public static final String EVENT_PROP_SLOW_REVERSE = "canPlaySlowReverse"; - public static final String EVENT_PROP_REVERSE = "canPlayReverse"; - public static final String EVENT_PROP_STEP_FORWARD = "canStepForward"; - public static final String EVENT_PROP_STEP_BACKWARD = "canStepBackward"; - - public static final String EVENT_PROP_DURATION = "duration"; - public static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration"; - public static final String EVENT_PROP_SEEKABLE_DURATION = "seekableDuration"; - public static final String EVENT_PROP_CURRENT_TIME = "currentTime"; - public static final String EVENT_PROP_SEEK_TIME = "seekTime"; - public static final String EVENT_PROP_NATURALSIZE = "naturalSize"; - public static final String EVENT_PROP_WIDTH = "width"; - public static final String EVENT_PROP_HEIGHT = "height"; - public static final String EVENT_PROP_ORIENTATION = "orientation"; - public static final String EVENT_PROP_METADATA = "metadata"; - public static final String EVENT_PROP_TARGET = "target"; - public static final String EVENT_PROP_METADATA_IDENTIFIER = "identifier"; - public static final String EVENT_PROP_METADATA_VALUE = "value"; - - public static final String EVENT_PROP_ERROR = "error"; - public static final String EVENT_PROP_WHAT = "what"; - public static final String EVENT_PROP_EXTRA = "extra"; - - private ThemedReactContext mThemedReactContext; - private RCTEventEmitter mEventEmitter; - - private Handler mProgressUpdateHandler = new Handler(); - private Runnable mProgressUpdateRunnable = null; - private Handler videoControlHandler = new Handler(); - private MediaController mediaController; - - private String mSrcUriString = null; - private String mSrcType = "mp4"; - private ReadableMap mRequestHeaders = null; - private boolean mSrcIsNetwork = false; - private boolean mSrcIsAsset = false; - private ScalableType mResizeMode = ScalableType.LEFT_TOP; - private boolean mRepeat = false; - private boolean mPaused = false; - private boolean mMuted = false; - private boolean mPreventsDisplaySleepDuringVideoPlayback = true; - private float mVolume = 1.0f; - private float mStereoPan = 0.0f; - private float mProgressUpdateInterval = 250.0f; - private float mRate = 1.0f; - private float mActiveRate = 1.0f; - private long mSeekTime = 0; - private boolean mPlayInBackground = false; - private boolean mBackgroundPaused = false; - private boolean mIsFullscreen = false; - - private int mMainVer = 0; - private int mPatchVer = 0; - - private boolean mMediaPlayerValid = false; // True if mMediaPlayer is in prepared, started, paused or completed state. - - private int mVideoDuration = 0; - private int mVideoBufferedDuration = 0; - private boolean isCompleted = false; - private boolean mUseNativeControls = false; - - public ReactVideoView(ThemedReactContext themedReactContext) { - super(themedReactContext); - - mThemedReactContext = themedReactContext; - mEventEmitter = themedReactContext.getJSModule(RCTEventEmitter.class); - themedReactContext.addLifecycleEventListener(this); - - initializeMediaPlayerIfNeeded(); - setSurfaceTextureListener(this); - - mProgressUpdateRunnable = new Runnable() { - @Override - public void run() { - - if (mMediaPlayerValid && !isCompleted && !mPaused && !mBackgroundPaused) { - WritableMap event = Arguments.createMap(); - event.putDouble(EVENT_PROP_CURRENT_TIME, mMediaPlayer.getCurrentPosition() / 1000.0); - event.putDouble(EVENT_PROP_PLAYABLE_DURATION, mVideoBufferedDuration / 1000.0); //TODO:mBufferUpdateRunnable - event.putDouble(EVENT_PROP_SEEKABLE_DURATION, mVideoDuration / 1000.0); - mEventEmitter.receiveEvent(getId(), Events.EVENT_PROGRESS.toString(), event); - - // Check for update after an interval - mProgressUpdateHandler.postDelayed(mProgressUpdateRunnable, Math.round(mProgressUpdateInterval)); - } - } - }; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mUseNativeControls) { - initializeMediaControllerIfNeeded(); - mediaController.show(); - } - - return super.onTouchEvent(event); - } - - @Override - @SuppressLint("DrawAllocation") - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - if (!changed || !mMediaPlayerValid) { - return; - } - - int videoWidth = getVideoWidth(); - int videoHeight = getVideoHeight(); - - if (videoWidth == 0 || videoHeight == 0) { - return; - } - - Size viewSize = new Size(getWidth(), getHeight()); - Size videoSize = new Size(videoWidth, videoHeight); - ScaleManager scaleManager = new ScaleManager(viewSize, videoSize); - Matrix matrix = scaleManager.getScaleMatrix(mScalableType); - if (matrix != null) { - setTransform(matrix); - } - } - - private void initializeMediaPlayerIfNeeded() { - if (mMediaPlayer == null) { - mMediaPlayerValid = false; - mMediaPlayer = new MediaPlayer(); - mMediaPlayer.setOnVideoSizeChangedListener(this); - mMediaPlayer.setOnErrorListener(this); - mMediaPlayer.setOnPreparedListener(this); - mMediaPlayer.setOnBufferingUpdateListener(this); - mMediaPlayer.setOnSeekCompleteListener(this); - mMediaPlayer.setOnCompletionListener(this); - mMediaPlayer.setOnInfoListener(this); - if (Build.VERSION.SDK_INT >= 23) { - mMediaPlayer.setOnTimedMetaDataAvailableListener(new TimedMetaDataAvailableListener()); - } - } - } - - private void initializeMediaControllerIfNeeded() { - if (mediaController == null) { - mediaController = new MediaController(this.getContext()); - } - } - - public void cleanupMediaPlayerResources() { - if ( mediaController != null ) { - mediaController.hide(); - } - if ( mMediaPlayer != null ) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - mMediaPlayer.setOnTimedMetaDataAvailableListener(null); - } - mMediaPlayerValid = false; - release(); - } - if (mIsFullscreen) { - setFullscreen(false); - } - if (mThemedReactContext != null) { - mThemedReactContext.removeLifecycleEventListener(this); - mThemedReactContext = null; - } - } - - public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders) { - setSrc(uriString, type, isNetwork, isAsset, requestHeaders, 0, 0); - } - - public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders, final int expansionMainVersion, final int expansionPatchVersion) { - - mSrcUriString = uriString; - mSrcType = type; - mSrcIsNetwork = isNetwork; - mSrcIsAsset = isAsset; - mRequestHeaders = requestHeaders; - mMainVer = expansionMainVersion; - mPatchVer = expansionPatchVersion; - - - mMediaPlayerValid = false; - mVideoDuration = 0; - mVideoBufferedDuration = 0; - - initializeMediaPlayerIfNeeded(); - mMediaPlayer.reset(); - - try { - if (isNetwork) { - // Use the shared CookieManager to access the cookies - // set by WebViews inside the same app - CookieManager cookieManager = CookieManager.getInstance(); - - Uri parsedUrl = Uri.parse(uriString); - Uri.Builder builtUrl = parsedUrl.buildUpon(); - - String cookie = cookieManager.getCookie(builtUrl.build().toString()); - - Map headers = new HashMap(); - - if (cookie != null) { - headers.put("Cookie", cookie); - } - - if (mRequestHeaders != null) { - headers.putAll(toStringMap(mRequestHeaders)); - } - - /* According to https://github.com/react-native-community/react-native-video/pull/537 - * there is an issue with this where it can cause a IOException. - * TODO: diagnose this exception and fix it - */ - setDataSource(mThemedReactContext, parsedUrl, headers); - } else if (isAsset) { - if (uriString.startsWith("content://")) { - Uri parsedUrl = Uri.parse(uriString); - setDataSource(mThemedReactContext, parsedUrl); - } else { - setDataSource(uriString); - } - } else { - ZipResourceFile expansionFile= null; - AssetFileDescriptor fd= null; - if(mMainVer>0) { - try { - expansionFile = APKExpansionSupport.getAPKExpansionZipFile(mThemedReactContext, mMainVer, mPatchVer); - fd = expansionFile.getAssetFileDescriptor(uriString.replace(".mp4","") + ".mp4"); - } catch (IOException e) { - e.printStackTrace(); - } catch (NullPointerException e) { - e.printStackTrace(); - } - } - if(fd==null) { - int identifier = mThemedReactContext.getResources().getIdentifier( - uriString, - "drawable", - mThemedReactContext.getPackageName() - ); - if (identifier == 0) { - identifier = mThemedReactContext.getResources().getIdentifier( - uriString, - "raw", - mThemedReactContext.getPackageName() - ); - } - setRawData(identifier); - } - else { - setDataSource(fd.getFileDescriptor(), fd.getStartOffset(),fd.getLength()); - } - } - } catch (Exception e) { - e.printStackTrace(); - return; - } - - WritableMap src = Arguments.createMap(); - - WritableMap wRequestHeaders = Arguments.createMap(); - wRequestHeaders.merge(mRequestHeaders); - - src.putString(ReactVideoViewManager.PROP_SRC_URI, uriString); - src.putString(ReactVideoViewManager.PROP_SRC_TYPE, type); - src.putMap(ReactVideoViewManager.PROP_SRC_HEADERS, wRequestHeaders); - src.putBoolean(ReactVideoViewManager.PROP_SRC_IS_NETWORK, isNetwork); - if(mMainVer>0) { - src.putInt(ReactVideoViewManager.PROP_SRC_MAINVER, mMainVer); - if(mPatchVer>0) { - src.putInt(ReactVideoViewManager.PROP_SRC_PATCHVER, mPatchVer); - } - } - WritableMap event = Arguments.createMap(); - event.putMap(ReactVideoViewManager.PROP_SRC, src); - mEventEmitter.receiveEvent(getId(), Events.EVENT_LOAD_START.toString(), event); - isCompleted = false; - - try { - prepareAsync(this); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void setResizeModeModifier(final ScalableType resizeMode) { - mResizeMode = resizeMode; - - if (mMediaPlayerValid) { - setScalableType(resizeMode); - invalidate(); - } - } - - public void setRepeatModifier(final boolean repeat) { - - mRepeat = repeat; - - if (mMediaPlayerValid) { - setLooping(repeat); - } - } - - public void setPausedModifier(final boolean paused) { - mPaused = paused; - - if (!mMediaPlayerValid) { - return; - } - - if (mPaused) { - if (mMediaPlayer.isPlaying()) { - pause(); - } - } else { - if (!mMediaPlayer.isPlaying()) { - start(); - // Setting the rate unpauses, so we have to wait for an unpause - if (mRate != mActiveRate) { - setRateModifier(mRate); - } - - // Also Start the Progress Update Handler - mProgressUpdateHandler.post(mProgressUpdateRunnable); - } - } - setKeepScreenOn(!mPaused && mPreventsDisplaySleepDuringVideoPlayback); - } - - // reduces the volume based on stereoPan - private float calulateRelativeVolume() { - float relativeVolume = (mVolume * (1 - Math.abs(mStereoPan))); - // only one decimal allowed - BigDecimal roundRelativeVolume = new BigDecimal(relativeVolume).setScale(1, BigDecimal.ROUND_HALF_UP); - return roundRelativeVolume.floatValue(); - } - - public void setPreventsDisplaySleepDuringVideoPlaybackModifier(final boolean preventsDisplaySleepDuringVideoPlayback) { - mPreventsDisplaySleepDuringVideoPlayback = preventsDisplaySleepDuringVideoPlayback; - - if (!mMediaPlayerValid) { - return; - } - - mMediaPlayer.setScreenOnWhilePlaying(mPreventsDisplaySleepDuringVideoPlayback); - setKeepScreenOn(mPreventsDisplaySleepDuringVideoPlayback); - } - - public void setMutedModifier(final boolean muted) { - mMuted = muted; - - if (!mMediaPlayerValid) { - return; - } - - if (mMuted) { - setVolume(0, 0); - } else if (mStereoPan < 0) { - // louder on the left channel - setVolume(mVolume, calulateRelativeVolume()); - } else if (mStereoPan > 0) { - // louder on the right channel - setVolume(calulateRelativeVolume(), mVolume); - } else { - // same volume on both channels - setVolume(mVolume, mVolume); - } - } - - public void setVolumeModifier(final float volume) { - mVolume = volume; - setMutedModifier(mMuted); - } - - public void setStereoPan(final float stereoPan) { - mStereoPan = stereoPan; - setMutedModifier(mMuted); - } - - public void setProgressUpdateInterval(final float progressUpdateInterval) { - mProgressUpdateInterval = progressUpdateInterval; - } - - public void setRateModifier(final float rate) { - mRate = rate; - - if (mMediaPlayerValid) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!mPaused) { // Applying the rate while paused will cause the video to start - /* Per https://stackoverflow.com/questions/39442522/setplaybackparams-causes-illegalstateexception - * Some devices throw an IllegalStateException if you set the rate without first calling reset() - * TODO: Call reset() then reinitialize the player - */ - try { - mMediaPlayer.setPlaybackParams(mMediaPlayer.getPlaybackParams().setSpeed(rate)); - mActiveRate = rate; - } catch (Exception e) { - Log.e(ReactVideoViewManager.REACT_CLASS, "Unable to set rate, unsupported on this device"); - } - } - } else { - Log.e(ReactVideoViewManager.REACT_CLASS, "Setting playback rate is not yet supported on Android versions below 6.0"); - } - } - } - - public void setFullscreen(boolean isFullscreen) { - if (isFullscreen == mIsFullscreen) { - return; // Avoid generating events when nothing is changing - } - mIsFullscreen = isFullscreen; - - Activity activity = mThemedReactContext.getCurrentActivity(); - if (activity == null) { - return; - } - Window window = activity.getWindow(); - View decorView = window.getDecorView(); - int uiOptions; - if (mIsFullscreen) { - if (Build.VERSION.SDK_INT >= 19) { // 4.4+ - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | SYSTEM_UI_FLAG_FULLSCREEN; - } else { - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_FULLSCREEN; - } - mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_WILL_PRESENT.toString(), null); - decorView.setSystemUiVisibility(uiOptions); - mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_DID_PRESENT.toString(), null); - } else { - uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; - mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_WILL_DISMISS.toString(), null); - decorView.setSystemUiVisibility(uiOptions); - mEventEmitter.receiveEvent(getId(), Events.EVENT_FULLSCREEN_DID_DISMISS.toString(), null); - } - } - - public void applyModifiers() { - setResizeModeModifier(mResizeMode); - setRepeatModifier(mRepeat); - setPausedModifier(mPaused); - setMutedModifier(mMuted); - setPreventsDisplaySleepDuringVideoPlaybackModifier(mPreventsDisplaySleepDuringVideoPlayback); - setProgressUpdateInterval(mProgressUpdateInterval); - setRateModifier(mRate); - } - - public void setPlayInBackground(final boolean playInBackground) { - - mPlayInBackground = playInBackground; - } - - public void setControls(boolean controls) { - this.mUseNativeControls = controls; - } - - @Override - public void onPrepared(MediaPlayer mp) { - - mMediaPlayerValid = true; - mVideoDuration = mp.getDuration(); - - WritableMap naturalSize = Arguments.createMap(); - naturalSize.putInt(EVENT_PROP_WIDTH, mp.getVideoWidth()); - naturalSize.putInt(EVENT_PROP_HEIGHT, mp.getVideoHeight()); - if (mp.getVideoWidth() > mp.getVideoHeight()) - naturalSize.putString(EVENT_PROP_ORIENTATION, "landscape"); - else - naturalSize.putString(EVENT_PROP_ORIENTATION, "portrait"); - - WritableMap event = Arguments.createMap(); - event.putDouble(EVENT_PROP_DURATION, mVideoDuration / 1000.0); - event.putDouble(EVENT_PROP_CURRENT_TIME, mp.getCurrentPosition() / 1000.0); - event.putMap(EVENT_PROP_NATURALSIZE, naturalSize); - // TODO: Actually check if you can. - event.putBoolean(EVENT_PROP_FAST_FORWARD, true); - event.putBoolean(EVENT_PROP_SLOW_FORWARD, true); - event.putBoolean(EVENT_PROP_SLOW_REVERSE, true); - event.putBoolean(EVENT_PROP_REVERSE, true); - event.putBoolean(EVENT_PROP_FAST_FORWARD, true); - event.putBoolean(EVENT_PROP_STEP_BACKWARD, true); - event.putBoolean(EVENT_PROP_STEP_FORWARD, true); - mEventEmitter.receiveEvent(getId(), Events.EVENT_LOAD.toString(), event); - - applyModifiers(); - - if (mUseNativeControls) { - initializeMediaControllerIfNeeded(); - mediaController.setMediaPlayer(this); - mediaController.setAnchorView(this); - - videoControlHandler.post(new Runnable() { - @Override - public void run() { - mediaController.setEnabled(true); - mediaController.show(); - } - }); - } - - selectTimedMetadataTrack(mp); - } - - @Override - public boolean onError(MediaPlayer mp, int what, int extra) { - - WritableMap error = Arguments.createMap(); - error.putInt(EVENT_PROP_WHAT, what); - error.putInt(EVENT_PROP_EXTRA, extra); - WritableMap event = Arguments.createMap(); - event.putMap(EVENT_PROP_ERROR, error); - mEventEmitter.receiveEvent(getId(), Events.EVENT_ERROR.toString(), event); - return true; - } - - @Override - public boolean onInfo(MediaPlayer mp, int what, int extra) { - switch (what) { - case MediaPlayer.MEDIA_INFO_BUFFERING_START: - mEventEmitter.receiveEvent(getId(), Events.EVENT_STALLED.toString(), Arguments.createMap()); - break; - case MediaPlayer.MEDIA_INFO_BUFFERING_END: - mEventEmitter.receiveEvent(getId(), Events.EVENT_RESUME.toString(), Arguments.createMap()); - break; - case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: - mEventEmitter.receiveEvent(getId(), Events.EVENT_READY_FOR_DISPLAY.toString(), Arguments.createMap()); - break; - - default: - } - return false; - } - - @Override - public void onBufferingUpdate(MediaPlayer mp, int percent) { - selectTimedMetadataTrack(mp); - mVideoBufferedDuration = (int) Math.round((double) (mVideoDuration * percent) / 100.0); - } - - public void onSeekComplete(MediaPlayer mp) { - WritableMap event = Arguments.createMap(); - event.putDouble(EVENT_PROP_CURRENT_TIME, getCurrentPosition() / 1000.0); - event.putDouble(EVENT_PROP_SEEK_TIME, mSeekTime / 1000.0); - mEventEmitter.receiveEvent(getId(), Events.EVENT_SEEK.toString(), event); - mSeekTime = 0; - } - - @Override - public void seekTo(int msec) { - if (mMediaPlayerValid) { - mSeekTime = msec; - mMediaPlayer.seekTo(msec, MediaPlayer.SEEK_CLOSEST); - if (isCompleted && mVideoDuration != 0 && msec < mVideoDuration) { - isCompleted = false; - } - } - } - - @Override - public int getBufferPercentage() { - return 0; - } - - @Override - public boolean canPause() { - return true; - } - - @Override - public boolean canSeekBackward() { - return true; - } - - @Override - public boolean canSeekForward() { - return true; - } - - @Override - public int getAudioSessionId() { - return 0; - } - - @Override - public void onCompletion(MediaPlayer mp) { - isCompleted = true; - mEventEmitter.receiveEvent(getId(), Events.EVENT_END.toString(), null); - if (!mRepeat) { - setKeepScreenOn(false); - } - } - - // This is not fully tested and does not work for all forms of timed metadata - @TargetApi(23) // 6.0 - public class TimedMetaDataAvailableListener - implements MediaPlayer.OnTimedMetaDataAvailableListener - { - public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data) { - WritableMap event = Arguments.createMap(); - - try { - String rawMeta = new String(data.getMetaData(), "UTF-8"); - WritableMap id3 = Arguments.createMap(); - - id3.putString(EVENT_PROP_METADATA_VALUE, rawMeta.substring(rawMeta.lastIndexOf("\u0003") + 1)); - id3.putString(EVENT_PROP_METADATA_IDENTIFIER, "id3/TDEN"); - - WritableArray metadata = new WritableNativeArray(); - - metadata.pushMap(id3); - - event.putArray(EVENT_PROP_METADATA, metadata); - event.putDouble(EVENT_PROP_TARGET, getId()); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - - mEventEmitter.receiveEvent(getId(), Events.EVENT_TIMED_METADATA.toString(), event); - } - } - - @Override - protected void onDetachedFromWindow() { - mMediaPlayerValid = false; - super.onDetachedFromWindow(); - setKeepScreenOn(false); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - if(mMainVer>0) { - setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders, mMainVer, mPatchVer); - } - else { - setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders); - } - setKeepScreenOn(mPreventsDisplaySleepDuringVideoPlayback); - } - - @Override - public void onHostPause() { - if (mMediaPlayerValid && !mPaused && !mPlayInBackground) { - /* Pause the video in background - * Don't update the paused prop, developers should be able to update it on background - * so that when you return to the app the video is paused - */ - mBackgroundPaused = true; - mMediaPlayer.pause(); - } - } - - @Override - public void onHostResume() { - mBackgroundPaused = false; - if (mMediaPlayerValid && !mPlayInBackground && !mPaused) { - new Handler().post(new Runnable() { - @Override - public void run() { - // Restore original state - setPausedModifier(false); - } - }); - } - } - - @Override - public void onHostDestroy() { - } - - /** - * toStringMap converts a {@link ReadableMap} into a HashMap. - * - * @param readableMap The ReadableMap to be conveted. - * @return A HashMap containing the data that was in the ReadableMap. - * @see 'Adapted from https://github.com/artemyarulin/react-native-eval/blob/master/android/src/main/java/com/evaluator/react/ConversionUtil.java' - */ - public static Map toStringMap(@Nullable ReadableMap readableMap) { - Map result = new HashMap<>(); - if (readableMap == null) - return result; - - com.facebook.react.bridge.ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - result.put(key, readableMap.getString(key)); - } - - return result; - } - - // Select track (so we can use it to listen to timed meta data updates) - private void selectTimedMetadataTrack(MediaPlayer mp) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return; - } - try { // It's possible this could throw an exception if the framework doesn't support getting track info - MediaPlayer.TrackInfo[] trackInfo = mp.getTrackInfo(); - for (int i = 0; i < trackInfo.length; ++i) { - if (trackInfo[i].getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { - mp.selectTrack(i); - break; - } - } - } catch (Exception e) {} - } -} diff --git a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java b/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java deleted file mode 100644 index 59efab49..00000000 --- a/android/src/main/java/com/brentvatne/react/ReactVideoViewManager.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.brentvatne.react; - -import com.brentvatne.react.ReactVideoView.Events; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.MapBuilder; -import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.SimpleViewManager; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.events.RCTEventEmitter; -import com.yqritc.scalablevideoview.ScalableType; - -import javax.annotation.Nullable; -import java.util.Map; - -public class ReactVideoViewManager extends SimpleViewManager { - - public static final String REACT_CLASS = "RCTVideo"; - - public static final String PROP_SRC = "src"; - public static final String PROP_SRC_URI = "uri"; - public static final String PROP_SRC_TYPE = "type"; - public static final String PROP_SRC_HEADERS = "requestHeaders"; - public static final String PROP_SRC_IS_NETWORK = "isNetwork"; - public static final String PROP_SRC_MAINVER = "mainVer"; - public static final String PROP_SRC_PATCHVER = "patchVer"; - public static final String PROP_SRC_IS_ASSET = "isAsset"; - public static final String PROP_RESIZE_MODE = "resizeMode"; - public static final String PROP_REPEAT = "repeat"; - public static final String PROP_PAUSED = "paused"; - public static final String PROP_MUTED = "muted"; - public static final String PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = "preventsDisplaySleepDuringVideoPlayback"; - public static final String PROP_VOLUME = "volume"; - public static final String PROP_STEREO_PAN = "stereoPan"; - public static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"; - public static final String PROP_SEEK = "seek"; - public static final String PROP_RATE = "rate"; - public static final String PROP_FULLSCREEN = "fullscreen"; - public static final String PROP_PLAY_IN_BACKGROUND = "playInBackground"; - public static final String PROP_CONTROLS = "controls"; - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - protected ReactVideoView createViewInstance(ThemedReactContext themedReactContext) { - return new ReactVideoView(themedReactContext); - } - - @Override - public void onDropViewInstance(ReactVideoView view) { - super.onDropViewInstance(view); - view.cleanupMediaPlayerResources(); - } - - @Override - @Nullable - public Map getExportedCustomDirectEventTypeConstants() { - MapBuilder.Builder builder = MapBuilder.builder(); - for (Events event : Events.values()) { - builder.put(event.toString(), MapBuilder.of("registrationName", event.toString())); - } - return builder.build(); - } - - @Override - @Nullable - public Map getExportedViewConstants() { - return MapBuilder.of( - "ScaleNone", Integer.toString(ScalableType.LEFT_TOP.ordinal()), - "ScaleToFill", Integer.toString(ScalableType.FIT_XY.ordinal()), - "ScaleAspectFit", Integer.toString(ScalableType.FIT_CENTER.ordinal()), - "ScaleAspectFill", Integer.toString(ScalableType.CENTER_CROP.ordinal()) - ); - } - - @ReactProp(name = PROP_SRC) - public void setSrc(final ReactVideoView videoView, @Nullable ReadableMap src) { - int mainVer = src.getInt(PROP_SRC_MAINVER); - int patchVer = src.getInt(PROP_SRC_PATCHVER); - if(mainVer<0) { mainVer = 0; } - if(patchVer<0) { patchVer = 0; } - if(mainVer>0) { - videoView.setSrc( - src.getString(PROP_SRC_URI), - src.getString(PROP_SRC_TYPE), - src.getBoolean(PROP_SRC_IS_NETWORK), - src.getBoolean(PROP_SRC_IS_ASSET), - src.getMap(PROP_SRC_HEADERS), - mainVer, - patchVer - ); - } - else { - videoView.setSrc( - src.getString(PROP_SRC_URI), - src.getString(PROP_SRC_TYPE), - src.getBoolean(PROP_SRC_IS_NETWORK), - src.getBoolean(PROP_SRC_IS_ASSET), - src.getMap(PROP_SRC_HEADERS) - ); - } - } - - @ReactProp(name = PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK) - public void setPropPreventsDisplaySleepDuringVideoPlayback(final ReactVideoView videoView, final boolean doPreventSleep) { - videoView.setPreventsDisplaySleepDuringVideoPlaybackModifier(doPreventSleep); - } - - @ReactProp(name = PROP_RESIZE_MODE) - public void setResizeMode(final ReactVideoView videoView, final String resizeModeOrdinalString) { - videoView.setResizeModeModifier(ScalableType.values()[Integer.parseInt(resizeModeOrdinalString)]); - } - - @ReactProp(name = PROP_REPEAT, defaultBoolean = false) - public void setRepeat(final ReactVideoView videoView, final boolean repeat) { - videoView.setRepeatModifier(repeat); - } - - @ReactProp(name = PROP_PAUSED, defaultBoolean = false) - public void setPaused(final ReactVideoView videoView, final boolean paused) { - videoView.setPausedModifier(paused); - } - - @ReactProp(name = PROP_MUTED, defaultBoolean = false) - public void setMuted(final ReactVideoView videoView, final boolean muted) { - videoView.setMutedModifier(muted); - } - - @ReactProp(name = PROP_VOLUME, defaultFloat = 1.0f) - public void setVolume(final ReactVideoView videoView, final float volume) { - videoView.setVolumeModifier(volume); - } - - @ReactProp(name = PROP_STEREO_PAN) - public void setStereoPan(final ReactVideoView videoView, final float stereoPan) { - videoView.setStereoPan(stereoPan); - } - - @ReactProp(name = PROP_PROGRESS_UPDATE_INTERVAL, defaultFloat = 250.0f) - public void setProgressUpdateInterval(final ReactVideoView videoView, final float progressUpdateInterval) { - videoView.setProgressUpdateInterval(progressUpdateInterval); - } - - @ReactProp(name = PROP_SEEK) - public void setSeek(final ReactVideoView videoView, final float seek) { - videoView.seekTo(Math.round(seek * 1000.0f)); - } - - @ReactProp(name = PROP_RATE) - public void setRate(final ReactVideoView videoView, final float rate) { - videoView.setRateModifier(rate); - } - - @ReactProp(name = PROP_FULLSCREEN, defaultBoolean = false) - public void setFullscreen(final ReactVideoView videoView, final boolean fullscreen) { - videoView.setFullscreen(fullscreen); - } - - @ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false) - public void setPlayInBackground(final ReactVideoView videoView, final boolean playInBackground) { - videoView.setPlayInBackground(playInBackground); - } - - @ReactProp(name = PROP_CONTROLS, defaultBoolean = false) - public void setControls(final ReactVideoView videoView, final boolean controls) { - videoView.setControls(controls); - } -} diff --git a/android-exoplayer/src/main/java/com/brentvatne/receiver/AudioBecomingNoisyReceiver.java b/android/src/main/java/com/brentvatne/receiver/AudioBecomingNoisyReceiver.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/receiver/AudioBecomingNoisyReceiver.java rename to android/src/main/java/com/brentvatne/receiver/AudioBecomingNoisyReceiver.java diff --git a/android-exoplayer/src/main/java/com/brentvatne/receiver/BecomingNoisyListener.java b/android/src/main/java/com/brentvatne/receiver/BecomingNoisyListener.java similarity index 100% rename from android-exoplayer/src/main/java/com/brentvatne/receiver/BecomingNoisyListener.java rename to android/src/main/java/com/brentvatne/receiver/BecomingNoisyListener.java diff --git a/android-exoplayer/src/main/res/layout/exo_player_control_view.xml b/android/src/main/res/layout/exo_player_control_view.xml similarity index 100% rename from android-exoplayer/src/main/res/layout/exo_player_control_view.xml rename to android/src/main/res/layout/exo_player_control_view.xml diff --git a/android-exoplayer/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml similarity index 100% rename from android-exoplayer/src/main/res/values/strings.xml rename to android/src/main/res/values/strings.xml diff --git a/examples/basic/android/settings.gradle b/examples/basic/android/settings.gradle index 29cf817a..a78bc672 100644 --- a/examples/basic/android/settings.gradle +++ b/examples/basic/android/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = 'VideoPlayer' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':react-native-video' -project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android-exoplayer') +project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android') include ':app' diff --git a/package.json b/package.json index a309f21e..40c3f72c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "xbasic": "yarn --cwd examples/basic" }, "files": [ - "android-exoplayer", "android", "dom", "ios",