feat: add plugins management (#3909)
This commit is contained in:
parent
3cfb96adb9
commit
91d27a6009
@ -123,6 +123,7 @@ import com.brentvatne.common.react.VideoEventEmitter;
|
||||
import com.brentvatne.common.toolbox.DebugLog;
|
||||
import com.brentvatne.react.BuildConfig;
|
||||
import com.brentvatne.react.R;
|
||||
import com.brentvatne.react.ReactNativeVideoManager;
|
||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
||||
import com.brentvatne.receiver.BecomingNoisyListener;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
@ -258,6 +259,9 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
private long lastDuration = -1;
|
||||
|
||||
private boolean viewHasDropped = false;
|
||||
|
||||
private String instanceId = String.valueOf(UUID.randomUUID());
|
||||
|
||||
private void updateProgress() {
|
||||
if (player != null) {
|
||||
if (playerControlView != null && isPlayingAd() && controls) {
|
||||
@ -756,6 +760,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
.setLoadControl(loadControl)
|
||||
.setMediaSourceFactory(mediaSourceFactory)
|
||||
.build();
|
||||
ReactNativeVideoManager.Companion.getInstance().onInstanceCreated(instanceId, player);
|
||||
refreshDebugState();
|
||||
player.addListener(self);
|
||||
player.setVolume(muted ? 0.f : audioVolume * 1);
|
||||
@ -1150,6 +1155,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
player.removeListener(this);
|
||||
trackSelector = null;
|
||||
|
||||
ReactNativeVideoManager.Companion.getInstance().onInstanceRemoved(instanceId, player);
|
||||
player = null;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import com.brentvatne.common.api.SubtitleStyle;
|
||||
import com.brentvatne.common.react.VideoEventEmitter;
|
||||
import com.brentvatne.common.toolbox.DebugLog;
|
||||
import com.brentvatne.common.toolbox.ReactBridgeUtils;
|
||||
import com.brentvatne.react.ReactNativeVideoManager;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
@ -97,12 +98,14 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
@NonNull
|
||||
@Override
|
||||
protected ReactExoplayerView createViewInstance(@NonNull ThemedReactContext themedReactContext) {
|
||||
ReactNativeVideoManager.Companion.getInstance().registerView(this);
|
||||
return new ReactExoplayerView(themedReactContext, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDropViewInstance(ReactExoplayerView view) {
|
||||
view.cleanUpResources();
|
||||
ReactNativeVideoManager.Companion.getInstance().unregisterView(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
22
android/src/main/java/com/brentvatne/react/RNVPlugin.kt
Normal file
22
android/src/main/java/com/brentvatne/react/RNVPlugin.kt
Normal file
@ -0,0 +1,22 @@
|
||||
package com.brentvatne.react
|
||||
|
||||
/**
|
||||
* Plugin interface definition
|
||||
*/
|
||||
interface RNVPlugin {
|
||||
/**
|
||||
* Function called when a new player is created
|
||||
* @param id: a random string identifying the player
|
||||
* @param player: the instantiated player reference
|
||||
*/
|
||||
fun onInstanceCreated(id: String, player: Any)
|
||||
|
||||
/**
|
||||
* Function called when a player should be destroyed
|
||||
* when this callback is called, the plugin shall free all
|
||||
* resources and release all reference to Player object
|
||||
* @param id: a random string identifying the player
|
||||
* @param player: the player to release
|
||||
*/
|
||||
fun onInstanceRemoved(id: String, player: Any)
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.brentvatne.react
|
||||
|
||||
import com.brentvatne.common.toolbox.DebugLog
|
||||
import com.brentvatne.exoplayer.ReactExoplayerViewManager
|
||||
|
||||
/**
|
||||
* ReactNativeVideoManager is a singleton class which allows to manipulate / the global state of the app
|
||||
* It handles the list of <Video view instanced and registration of plugins
|
||||
*/
|
||||
class ReactNativeVideoManager : RNVPlugin {
|
||||
companion object {
|
||||
private const val TAG = "ReactNativeVideoManager"
|
||||
|
||||
@Volatile
|
||||
private var instance: ReactNativeVideoManager? = null
|
||||
|
||||
/**
|
||||
* Singleton accessor
|
||||
*/
|
||||
fun getInstance(): ReactNativeVideoManager =
|
||||
instance ?: synchronized(this) {
|
||||
instance ?: ReactNativeVideoManager().also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
private var instanceList: ArrayList<ReactExoplayerViewManager> = ArrayList()
|
||||
private var pluginList: ArrayList<RNVPlugin> = ArrayList()
|
||||
|
||||
/**
|
||||
* register a new ReactExoplayerViewManager in the managed list
|
||||
*/
|
||||
fun registerView(newInstance: ReactExoplayerViewManager): () -> Boolean =
|
||||
{
|
||||
if (instanceList.size > 2) {
|
||||
DebugLog.d(TAG, "multiple Video displayed ?")
|
||||
}
|
||||
instanceList.add(newInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister existing ReactExoplayerViewManager in the managed list
|
||||
*/
|
||||
fun unregisterView(newInstance: ReactExoplayerViewManager): () -> Boolean =
|
||||
{
|
||||
instanceList.remove(newInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* register a new plugin in the managed list
|
||||
*/
|
||||
fun registerPlugin(plugin: RNVPlugin) {
|
||||
pluginList.add(plugin)
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister a plugin from the managed list
|
||||
*/
|
||||
fun unregisterPlugin(plugin: RNVPlugin) {
|
||||
pluginList.remove(plugin)
|
||||
return
|
||||
}
|
||||
|
||||
override fun onInstanceCreated(id: String, player: Any) {
|
||||
pluginList.forEach { it.onInstanceCreated(id, player) }
|
||||
}
|
||||
|
||||
override fun onInstanceRemoved(id: String, player: Any) {
|
||||
pluginList.forEach { it.onInstanceRemoved(id, player) }
|
||||
}
|
||||
}
|
@ -2,5 +2,6 @@
|
||||
"caching": "Caching",
|
||||
"misc": "Misc",
|
||||
"debug": "Debugging",
|
||||
"new-arch": "New Architecture"
|
||||
"new-arch": "New Architecture",
|
||||
"plugin": "Plugin (experimental)"
|
||||
}
|
125
docs/pages/other/plugin.md
Normal file
125
docs/pages/other/plugin.md
Normal file
@ -0,0 +1,125 @@
|
||||
# Plugin (experimental)
|
||||
|
||||
Since Version 6.4.0, it is possible to create plugins for analytics management and maybe much more.
|
||||
A sample plugin is available in the repository in: example/react-native-video-plugin-sample. (important FIXME, put sample link)
|
||||
|
||||
## Concept
|
||||
|
||||
Most of the analytics system which tracks player information (bitrate, errors, ...) can be integrated directly with Exoplayer or AVPlayer handles.
|
||||
|
||||
This plugin system allows none intrusive integration of analytics in the react-native-package. It shall be done in native language (kotlin/swift).
|
||||
|
||||
The idea behind this system is to be able to plug an analytics package to react native video without doing any code change (ideally).
|
||||
|
||||
Following documentation will show on how to create a new plugin for react native video
|
||||
|
||||
## Warning and consideration
|
||||
This is an experiental API, it is subject to change. The api with player is very simple but should be flexible enough to implement analytics system. If you need some metadata, you should implement setter in the new package you are creating.
|
||||
|
||||
As api is flexible, it makes possible to missuse the system. It is necessary to consider the player handle as read-only. If you modify player behavior, we cannot garanty the good behavior of react-native-video package.
|
||||
|
||||
## General
|
||||
|
||||
First you need to create a new react native package:
|
||||
````shell
|
||||
npx create-react-native-library@latest react-native-video-custom-analytics
|
||||
````
|
||||
|
||||
Both android and iOS implementation expose an interface `RNVPlugin`.
|
||||
Your `react-native-video-custom-analytics` shall implement this interface and register itself as a plugin for react native video.
|
||||
|
||||
## Android
|
||||
There is no special requierement for gradle file.
|
||||
You need two mandatory action to be able to receive player handle
|
||||
|
||||
### 1/ Create the plugin
|
||||
|
||||
First you should instanciate a class which extends `RNVPlugin`.
|
||||
|
||||
The proposed integration implement `RNVPlugin` directly inside the Module file (`VideoPluginSampleModule`).
|
||||
|
||||
The `RNVPlugin` interface only defines 2 functions, see description here under.
|
||||
|
||||
```kotlin
|
||||
/**
|
||||
* Function called when a new player is created
|
||||
* @param id: a random string identifying the player
|
||||
* @param player: the instantiated player reference
|
||||
*/
|
||||
fun onInstanceCreated(id: String, player: Any)
|
||||
/**
|
||||
* Function called when a player should be destroyed
|
||||
* when this callback is called, the plugin shall free all
|
||||
* resources and release all reference to Player object
|
||||
* @param id: a random string identifying the player
|
||||
* @param player: the player to release
|
||||
*/
|
||||
fun onInstanceRemoved(id: String, player: Any)
|
||||
````
|
||||
|
||||
### 2/ register the plugin
|
||||
|
||||
To register this allocated class in the main react native video package you should call following function:
|
||||
|
||||
```kotlin
|
||||
ReactNativeVideoManager.getInstance().registerPlugin(plugin)
|
||||
```
|
||||
The proposed integration register the instanciated class in `createNativeModules` entry point.
|
||||
|
||||
Your native module can now track Player updates directly from Player reference and report to backend.
|
||||
|
||||
## ios
|
||||
|
||||
### 1/ podspec integration
|
||||
|
||||
Your new module shall be able to access to react-native-video package, then we must declare it as a dependency of the new module you are creating.
|
||||
|
||||
```podfile
|
||||
s.dependency "react-native-video"
|
||||
````
|
||||
|
||||
### 2/ Create the plugin
|
||||
|
||||
First you should instanciate a class which extends `RNVPlugin`.
|
||||
|
||||
The proposed integration implement `RNVPlugin` directly inside the entry point of the module file (`VideoPluginSample`).
|
||||
|
||||
The `RNVPlugin` interface only defines 2 functions, see description here under.
|
||||
|
||||
```swift
|
||||
/**
|
||||
* Function called when a new player is created
|
||||
* @param player: the instantiated player reference
|
||||
*/
|
||||
func onInstanceCreated(player: Any)
|
||||
/**
|
||||
* Function called when a player should be destroyed
|
||||
* when this callback is called, the plugin shall free all
|
||||
* resources and release all reference to Player object
|
||||
* @param player: the player to release
|
||||
*/
|
||||
func onInstanceRemoved(player: Any)
|
||||
```
|
||||
|
||||
### 3/ Register the plugin
|
||||
|
||||
To register this allocated class in the main react native video package you should register it by calling this function:
|
||||
|
||||
```swift
|
||||
ReactNativeVideoManager.shared.registerPlugin(plugin: plugin)
|
||||
```
|
||||
|
||||
The proposed integration register the instanciated class in file `VideoPluginSample` in the init function:
|
||||
|
||||
```swift
|
||||
import react_native_video
|
||||
|
||||
...
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
ReactNativeVideoManager.shared.registerPlugin(plugin: self)
|
||||
}
|
||||
```
|
||||
|
||||
Your native module can now track Player updates directly from Player reference and report to backend.
|
@ -137,6 +137,7 @@ dependencies {
|
||||
}
|
||||
|
||||
implementation project(':react-native-video')
|
||||
implementation project(':react-native-video-plugin-sample')
|
||||
|
||||
constraints {
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") {
|
||||
|
@ -14,6 +14,7 @@ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||
import com.facebook.soloader.SoLoader
|
||||
import com.brentvatne.react.ReactVideoPackage
|
||||
import com.videopluginsample.VideoPluginSamplePackage
|
||||
|
||||
class MainApplication : Application(), ReactApplication {
|
||||
|
||||
@ -24,6 +25,7 @@ class MainApplication : Application(), ReactApplication {
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// add(MyReactNativePackage())
|
||||
add(ReactVideoPackage())
|
||||
add(VideoPluginSamplePackage())
|
||||
}
|
||||
|
||||
override fun getJSMainModuleName(): String = "src/index"
|
||||
|
@ -2,6 +2,9 @@ rootProject.name = 'videoplayer'
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
|
||||
include ':react-native-video-plugin-sample'
|
||||
project (':react-native-video-plugin-sample').projectDir = new File(rootProject.projectDir, '../../react-native-video-plugin-sample/android')
|
||||
|
||||
include ':react-native-video'
|
||||
project (':react-native-video').projectDir = new File(rootProject.projectDir, '../../../android')
|
||||
|
||||
|
@ -46,6 +46,7 @@ target 'videoplayer' do
|
||||
)
|
||||
|
||||
pod 'react-native-video', path: '../../..'
|
||||
pod 'react-native-video-plugin-sample', path: '../../react-native-video-plugin-sample'
|
||||
|
||||
target 'videoplayerTests' do
|
||||
inherit! :complete
|
||||
|
@ -1016,6 +1016,28 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-video-plugin-sample (0.0.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2024.01.01.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Codegen
|
||||
- React-Core
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- react-native-video
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-video/Video (6.2.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
@ -1324,6 +1346,7 @@ DEPENDENCIES:
|
||||
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
|
||||
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
|
||||
- react-native-video (from `../../..`)
|
||||
- react-native-video-plugin-sample (from `../../react-native-video-plugin-sample`)
|
||||
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
@ -1441,6 +1464,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
react-native-video:
|
||||
:path: "../../.."
|
||||
react-native-video-plugin-sample:
|
||||
:path: "../../react-native-video-plugin-sample"
|
||||
React-nativeconfig:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-NativeModulesApple:
|
||||
@ -1505,12 +1530,12 @@ SPEC CHECKSUMS:
|
||||
ExpoModulesCore: 2731dc119f8c1400636a994df4efbc19522defbd
|
||||
FBLazyVector: 4bc164e5b5e6cfc288d2b5ff28643ea15fa1a589
|
||||
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
|
||||
glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
|
||||
glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f
|
||||
hermes-engine: 01d3e052018c2a13937aca1860fbedbccd4a41b7
|
||||
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
||||
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
||||
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
|
||||
RCT-Folly: 045d6ecaa59d826c5736dfba0b2f4083ff8d79df
|
||||
RCT-Folly: 02617c592a293bd6d418e0a88ff4ee1f88329b47
|
||||
RCTDeprecation: b03c35057846b685b3ccadc9bfe43e349989cdb2
|
||||
RCTRequired: 194626909cfa8d39ca6663138c417bc6c431648c
|
||||
RCTTypeSafety: 552aff5b8e8341660594db00e53ac889682bc120
|
||||
@ -1535,6 +1560,7 @@ SPEC CHECKSUMS:
|
||||
React-logger: 29fa3e048f5f67fe396bc08af7606426d9bd7b5d
|
||||
React-Mapbuffer: 86703e9e4f6522053568300827b436ccc01e1101
|
||||
react-native-video: 59f262a2d87c998b747ca1f031efb6eba1c156b5
|
||||
react-native-video-plugin-sample: d3a93b7ad777cad7fa2c30473de75a2635ce5feb
|
||||
React-nativeconfig: 5d452e509d6fbedc1522e21b566451fc673ac6b7
|
||||
React-NativeModulesApple: 6560431301ffdab8df6212cc8c8eff779396d8e0
|
||||
React-perflogger: 32ed45d9cee02cf6639acae34251590dccd30994
|
||||
@ -1566,6 +1592,6 @@ SPEC CHECKSUMS:
|
||||
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
|
||||
Yoga: 45564236f670899c9739b1581a12b00ead5d391f
|
||||
|
||||
PODFILE CHECKSUM: dfb9633fc816e568fd6d90dde654d15acd66faa9
|
||||
PODFILE CHECKSUM: a73d485df51877001f2b04a5a4379cfa5a3ba8fa
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
|
@ -8,15 +8,16 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00E356F31AD99517003FC87E /* videoplayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* videoplayerTests.m */; };
|
||||
11C6209C7B72C624AC36CAD1 /* Pods_videoplayer_videoplayerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 594390EE3512A597F6D2CFC8 /* Pods_videoplayer_videoplayerTests.framework */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
208BB513171FFCC3277F9E0F /* Pods_videoplayer_videoplayerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5C7FBD972AC23420C9CAEF6 /* Pods_videoplayer_videoplayerTests.framework */; };
|
||||
20E2D2234B216472515590E5 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9B7A50CD29E62AE55CDBAC5 /* ExpoModulesProvider.swift */; };
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||
8564D8A0ECE6B35EF7A78EDB /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF6DF30451E50AB13568EFC /* ExpoModulesProvider.swift */; };
|
||||
A64041D5CF85945B698F6FD0 /* Pods_videoplayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4610D42AC113C0F184AAF5BC /* Pods_videoplayer.framework */; };
|
||||
C57DB7DC75FFA5378D941129 /* Pods_videoplayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 10FD7EDE51B5059CB0982AD2 /* Pods_videoplayer.framework */; };
|
||||
DA6F026ACB11B4361D7006B9 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 06EB80F4634394ABC14C45DC /* PrivacyInfo.xcprivacy */; };
|
||||
EC73F7EE64DE3B7F743B618D /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -33,22 +34,22 @@
|
||||
00E356EE1AD99517003FC87E /* videoplayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = videoplayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00E356F21AD99517003FC87E /* videoplayerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = videoplayerTests.m; sourceTree = "<group>"; };
|
||||
058979377AFD7ECE5B23DBEB /* Pods-videoplayer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer.release.xcconfig"; path = "Target Support Files/Pods-videoplayer/Pods-videoplayer.release.xcconfig"; sourceTree = "<group>"; };
|
||||
06EB80F4634394ABC14C45DC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = videoplayer/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
10FD7EDE51B5059CB0982AD2 /* Pods_videoplayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_videoplayer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07F961A680F5B00A75B9A /* videoplayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = videoplayer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = videoplayer/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = videoplayer/AppDelegate.mm; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = videoplayer/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = videoplayer/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = videoplayer/main.m; sourceTree = "<group>"; };
|
||||
327740C386721461467B91B2 /* Pods-videoplayer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer.release.xcconfig"; path = "Target Support Files/Pods-videoplayer/Pods-videoplayer.release.xcconfig"; sourceTree = "<group>"; };
|
||||
4610D42AC113C0F184AAF5BC /* Pods_videoplayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_videoplayer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5112808AA45F803BD0D3F411 /* Pods-videoplayer-videoplayerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer-videoplayerTests.release.xcconfig"; path = "Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
594390EE3512A597F6D2CFC8 /* Pods_videoplayer_videoplayerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_videoplayer_videoplayerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6E6DE29C8B861F4D5A4BBDEB /* Pods-videoplayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer.debug.xcconfig"; path = "Target Support Files/Pods-videoplayer/Pods-videoplayer.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
2F5C4E6DD1564FCB6C9B7B94 /* Pods-videoplayer-videoplayerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer-videoplayerTests.debug.xcconfig"; path = "Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7AF6DF30451E50AB13568EFC /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-videoplayer-videoplayerTests/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = videoplayer/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
9C018F4E223E0E71BA85ABC9 /* Pods-videoplayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer.debug.xcconfig"; path = "Target Support Files/Pods-videoplayer/Pods-videoplayer.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A5C7FBD972AC23420C9CAEF6 /* Pods_videoplayer_videoplayerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_videoplayer_videoplayerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B9B7A50CD29E62AE55CDBAC5 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-videoplayer/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||
CBE734469FBE698BF938A7EF /* Pods-videoplayer-videoplayerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer-videoplayerTests.debug.xcconfig"; path = "Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
CF1F0C5E1D8D8D557C4C7043 /* Pods-videoplayer-videoplayerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-videoplayer-videoplayerTests.release.xcconfig"; path = "Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -57,7 +58,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
11C6209C7B72C624AC36CAD1 /* Pods_videoplayer_videoplayerTests.framework in Frameworks */,
|
||||
208BB513171FFCC3277F9E0F /* Pods_videoplayer_videoplayerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -65,7 +66,8 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A64041D5CF85945B698F6FD0 /* Pods_videoplayer.framework in Frameworks */,
|
||||
EC73F7EE64DE3B7F743B618D /* BuildFile in Frameworks */,
|
||||
C57DB7DC75FFA5378D941129 /* Pods_videoplayer.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -107,8 +109,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
4610D42AC113C0F184AAF5BC /* Pods_videoplayer.framework */,
|
||||
594390EE3512A597F6D2CFC8 /* Pods_videoplayer_videoplayerTests.framework */,
|
||||
10FD7EDE51B5059CB0982AD2 /* Pods_videoplayer.framework */,
|
||||
A5C7FBD972AC23420C9CAEF6 /* Pods_videoplayer_videoplayerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@ -165,10 +167,10 @@
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6E6DE29C8B861F4D5A4BBDEB /* Pods-videoplayer.debug.xcconfig */,
|
||||
327740C386721461467B91B2 /* Pods-videoplayer.release.xcconfig */,
|
||||
CBE734469FBE698BF938A7EF /* Pods-videoplayer-videoplayerTests.debug.xcconfig */,
|
||||
5112808AA45F803BD0D3F411 /* Pods-videoplayer-videoplayerTests.release.xcconfig */,
|
||||
9C018F4E223E0E71BA85ABC9 /* Pods-videoplayer.debug.xcconfig */,
|
||||
058979377AFD7ECE5B23DBEB /* Pods-videoplayer.release.xcconfig */,
|
||||
2F5C4E6DD1564FCB6C9B7B94 /* Pods-videoplayer-videoplayerTests.debug.xcconfig */,
|
||||
CF1F0C5E1D8D8D557C4C7043 /* Pods-videoplayer-videoplayerTests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@ -188,13 +190,13 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "videoplayerTests" */;
|
||||
buildPhases = (
|
||||
C0C880E0881EE98C1792E57D /* [CP] Check Pods Manifest.lock */,
|
||||
05848CC282AE20BB2B2AA52D /* [CP] Check Pods Manifest.lock */,
|
||||
E0436766C647BDEAF9FD5ED3 /* [Expo] Configure project */,
|
||||
00E356EA1AD99517003FC87E /* Sources */,
|
||||
00E356EB1AD99517003FC87E /* Frameworks */,
|
||||
00E356EC1AD99517003FC87E /* Resources */,
|
||||
E3461B2529EDAA05BCA42787 /* [CP] Embed Pods Frameworks */,
|
||||
0765D094F5C79DBE6CC6386B /* [CP] Copy Pods Resources */,
|
||||
0F69B47FEB727B4EBBAC0C93 /* [CP] Embed Pods Frameworks */,
|
||||
8DEA7E188641F8CD9B4543DD /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -210,15 +212,15 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "videoplayer" */;
|
||||
buildPhases = (
|
||||
66FA7E36D064B737784DDFB7 /* [CP] Check Pods Manifest.lock */,
|
||||
4BC7B73D9362CA23BDA1E909 /* [CP] Check Pods Manifest.lock */,
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
43E82399B51FE7A2CADEE958 /* [Expo] Configure project */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
189A4605ED0B2F88CF1DCFA8 /* [CP] Embed Pods Frameworks */,
|
||||
F467D0E16E9AD72917847B43 /* [CP] Copy Pods Resources */,
|
||||
5580EE7ED1DD133A3CB36FB0 /* [CP] Embed Pods Frameworks */,
|
||||
4617BBDCD64674510B35868A /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -302,82 +304,7 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli')\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n";
|
||||
};
|
||||
0765D094F5C79DBE6CC6386B /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
189A4605ED0B2F88CF1DCFA8 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
43E82399B51FE7A2CADEE958 /* [Expo] Configure project */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[Expo] Configure project";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-videoplayer/expo-configure-project.sh\"\n";
|
||||
};
|
||||
66FA7E36D064B737784DDFB7 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-videoplayer-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C0C880E0881EE98C1792E57D /* [CP] Check Pods Manifest.lock */ = {
|
||||
05848CC282AE20BB2B2AA52D /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@ -399,6 +326,115 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
0F69B47FEB727B4EBBAC0C93 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
43E82399B51FE7A2CADEE958 /* [Expo] Configure project */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[Expo] Configure project";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-videoplayer/expo-configure-project.sh\"\n";
|
||||
};
|
||||
4617BBDCD64674510B35868A /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
4BC7B73D9362CA23BDA1E909 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-videoplayer-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
5580EE7ED1DD133A3CB36FB0 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8DEA7E188641F8CD9B4543DD /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E0436766C647BDEAF9FD5ED3 /* [Expo] Configure project */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
@ -418,40 +454,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-videoplayer-videoplayerTests/expo-configure-project.sh\"\n";
|
||||
};
|
||||
E3461B2529EDAA05BCA42787 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer-videoplayerTests/Pods-videoplayer-videoplayerTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F467D0E16E9AD72917847B43 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-videoplayer/Pods-videoplayer-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD10A7F022414F080027D42C /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -506,7 +508,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00E356F61AD99517003FC87E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = CBE734469FBE698BF938A7EF /* Pods-videoplayer-videoplayerTests.debug.xcconfig */;
|
||||
baseConfigurationReference = 2F5C4E6DD1564FCB6C9B7B94 /* Pods-videoplayer-videoplayerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
@ -534,7 +536,7 @@
|
||||
};
|
||||
00E356F71AD99517003FC87E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5112808AA45F803BD0D3F411 /* Pods-videoplayer-videoplayerTests.release.xcconfig */;
|
||||
baseConfigurationReference = CF1F0C5E1D8D8D557C4C7043 /* Pods-videoplayer-videoplayerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
@ -559,7 +561,7 @@
|
||||
};
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 6E6DE29C8B861F4D5A4BBDEB /* Pods-videoplayer.debug.xcconfig */;
|
||||
baseConfigurationReference = 9C018F4E223E0E71BA85ABC9 /* Pods-videoplayer.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@ -587,7 +589,7 @@
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 327740C386721461467B91B2 /* Pods-videoplayer.release.xcconfig */;
|
||||
baseConfigurationReference = 058979377AFD7ECE5B23DBEB /* Pods-videoplayer.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
@ -4,6 +4,7 @@
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"react-native-video": ["../../src/index"],
|
||||
"react-native-video-plugin-sample": ["../react-native-video-plugin-sample/src/index"],
|
||||
}
|
||||
},
|
||||
"jsx": "react",
|
||||
|
106
examples/react-native-video-plugin-sample/android/build.gradle
Normal file
106
examples/react-native-video-plugin-sample/android/build.gradle
Normal file
@ -0,0 +1,106 @@
|
||||
buildscript {
|
||||
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
||||
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["VideoPluginSample_kotlinVersion"]
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:7.2.1"
|
||||
// noinspection DifferentKotlinGradleVersion
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
def reactNativeArchitectures() {
|
||||
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
||||
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
||||
}
|
||||
|
||||
def isNewArchitectureEnabled() {
|
||||
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
||||
}
|
||||
|
||||
apply plugin: "com.android.library"
|
||||
apply plugin: "kotlin-android"
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
apply plugin: "com.facebook.react"
|
||||
}
|
||||
|
||||
def getExtOrDefault(name) {
|
||||
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["VideoPluginSample_" + name]
|
||||
}
|
||||
|
||||
def getExtOrIntegerDefault(name) {
|
||||
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["VideoPluginSample_" + name]).toInteger()
|
||||
}
|
||||
|
||||
def supportsNamespace() {
|
||||
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
||||
def major = parsed[0].toInteger()
|
||||
def minor = parsed[1].toInteger()
|
||||
|
||||
// Namespace support was added in 7.3.0
|
||||
return (major == 7 && minor >= 3) || major >= 8
|
||||
}
|
||||
|
||||
android {
|
||||
if (supportsNamespace()) {
|
||||
namespace "com.videopluginsample"
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
||||
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable "GradleCompatible"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
||||
def safeExtGet(prop) {
|
||||
return rootProject.ext.has(prop) ? rootProject.ext.get(prop) : project.properties["RNVideo_" + prop]
|
||||
}
|
||||
|
||||
def kotlin_version = getExtOrDefault("kotlinVersion")
|
||||
def media3_version = safeExtGet('media3Version')
|
||||
|
||||
dependencies {
|
||||
// For < 0.71, this will be from the local maven repo
|
||||
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation "com.facebook.react:react-native:+"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "androidx.media3:media3-exoplayer:$media3_version"
|
||||
implementation project(':react-native-video')
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
VideoPluginSample_kotlinVersion=1.7.0
|
||||
VideoPluginSample_minSdkVersion=21
|
||||
VideoPluginSample_targetSdkVersion=31
|
||||
VideoPluginSample_compileSdkVersion=31
|
||||
VideoPluginSample_ndkversion=21.4.7075529
|
@ -0,0 +1,3 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.videopluginsample">
|
||||
</manifest>
|
@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
</manifest>
|
@ -0,0 +1,50 @@
|
||||
package com.videopluginsample
|
||||
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.util.EventLogger
|
||||
import com.brentvatne.common.toolbox.DebugLog
|
||||
import com.brentvatne.react.RNVPlugin
|
||||
import com.facebook.react.bridge.Promise
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
||||
import com.facebook.react.bridge.ReactMethod
|
||||
|
||||
class VideoPluginSampleModule(reactContext: ReactApplicationContext) :
|
||||
ReactContextBaseJavaModule(reactContext), RNVPlugin, Player.Listener {
|
||||
|
||||
private val debugEventLogger = EventLogger("RNVPluginSample")
|
||||
|
||||
override fun getName(): String {
|
||||
return NAME
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun setMetadata(promise: Promise) {
|
||||
promise.resolve(true)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val NAME = "VideoPluginSample"
|
||||
const val TAG = "VideoPluginSampleModule"
|
||||
}
|
||||
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
DebugLog.e(TAG, "onPlayerError: " + error.errorCodeName)
|
||||
}
|
||||
|
||||
|
||||
override fun onInstanceCreated(id: String, player: Any) {
|
||||
if (player is ExoPlayer) {
|
||||
player.addAnalyticsListener(debugEventLogger)
|
||||
player.addListener(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInstanceRemoved(id: String, player: Any) {
|
||||
if (player is ExoPlayer) {
|
||||
player.removeAnalyticsListener(debugEventLogger)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.videopluginsample
|
||||
|
||||
import com.brentvatne.react.ReactNativeVideoManager
|
||||
import com.facebook.react.ReactPackage
|
||||
import com.facebook.react.bridge.NativeModule
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.uimanager.ViewManager
|
||||
|
||||
class VideoPluginSamplePackage : ReactPackage {
|
||||
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
||||
val plugin = VideoPluginSampleModule(reactContext)
|
||||
ReactNativeVideoManager.getInstance().registerPlugin(plugin)
|
||||
return listOf(plugin)
|
||||
}
|
||||
|
||||
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
||||
return emptyList()
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTViewManager.h>
|
@ -0,0 +1,14 @@
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
@interface RCT_EXTERN_MODULE(VideoPluginSample, NSObject)
|
||||
|
||||
RCT_EXTERN_METHOD(setMetadata:
|
||||
withResolver:(RCTPromiseResolveBlock)resolve
|
||||
withRejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,67 @@
|
||||
import react_native_video
|
||||
import AVFoundation
|
||||
import AVKit
|
||||
|
||||
@objc(VideoPluginSample)
|
||||
class VideoPluginSample: NSObject, RNVPlugin {
|
||||
private var _playerRateChangeObserver: NSKeyValueObservation?
|
||||
private var _playerCurrentItemChangeObserver: NSKeyValueObservation?
|
||||
private var _playerItemStatusObserver: NSKeyValueObservation?
|
||||
|
||||
/**
|
||||
* create an init function to register the plugin
|
||||
*/
|
||||
override init() {
|
||||
super.init()
|
||||
ReactNativeVideoManager.shared.registerPlugin(plugin: self)
|
||||
}
|
||||
|
||||
|
||||
@objc(withResolver:withRejecter:)
|
||||
func setMetadata(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
||||
resolve(true)
|
||||
}
|
||||
|
||||
/*
|
||||
* Handlers called on player creation and destructon
|
||||
*/
|
||||
func onInstanceCreated(id: String, player: Any) {
|
||||
if player is AVPlayer {
|
||||
let avPlayer = player as! AVPlayer
|
||||
NSLog("plug onInstanceCreated")
|
||||
_playerRateChangeObserver = avPlayer.observe(\.rate, options: [.old], changeHandler: handlePlaybackRateChange)
|
||||
_playerCurrentItemChangeObserver = avPlayer.observe(\.currentItem, options: [.old], changeHandler: handleCurrentItemChange)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func onInstanceRemoved(id: String, player: Any) {
|
||||
if player is AVPlayer {
|
||||
let avPlayer = player as! AVPlayer
|
||||
NSLog("plug onInstanceRemoved")
|
||||
_playerRateChangeObserver?.invalidate()
|
||||
_playerCurrentItemChangeObserver?.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* custom functions to be able to track AVPlayer state change
|
||||
*/
|
||||
func handlePlaybackRateChange(player: AVPlayer, change: NSKeyValueObservedChange<Float>) {
|
||||
NSLog("plugin: handlePlaybackRateChange \(change.oldValue)")
|
||||
}
|
||||
|
||||
func handlePlayerItemStatusChange(playerItem: AVPlayerItem, change _: NSKeyValueObservedChange<AVPlayerItem.Status>) {
|
||||
NSLog("plugin: handlePlayerItemStatusChange \(playerItem.status)")
|
||||
}
|
||||
|
||||
func handleCurrentItemChange(player: AVPlayer, change: NSKeyValueObservedChange<AVPlayerItem?>) {
|
||||
NSLog("plugin: handleCurrentItemChange \(player.currentItem)")
|
||||
guard let playerItem = player.currentItem else {
|
||||
_playerItemStatusObserver?.invalidate()
|
||||
return
|
||||
}
|
||||
|
||||
_playerItemStatusObserver = playerItem.observe(\.status, options: [.new, .old], changeHandler: handlePlayerItemStatusChange)
|
||||
}
|
||||
}
|
9
examples/react-native-video-plugin-sample/package.json
Normal file
9
examples/react-native-video-plugin-sample/package.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "react-native-video-plugin-sample",
|
||||
"version": "0.0.0",
|
||||
"description": "sample subpackage for react native video plugin",
|
||||
"main": "src/index",
|
||||
"author": " <> ()",
|
||||
"license": "UNLICENSED",
|
||||
"homepage": "#readme"
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
||||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "react-native-video-plugin-sample"
|
||||
s.version = package["version"]
|
||||
s.summary = package["description"]
|
||||
s.homepage = package["homepage"]
|
||||
s.license = package["license"]
|
||||
s.authors = package["author"]
|
||||
|
||||
s.platforms = { :ios => min_ios_version_supported }
|
||||
s.source = { :git => ".git", :tag => "#{s.version}" }
|
||||
|
||||
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
||||
s.dependency "react-native-video"
|
||||
|
||||
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
||||
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
||||
if respond_to?(:install_modules_dependencies, true)
|
||||
install_modules_dependencies(s)
|
||||
else
|
||||
s.dependency "React-Core"
|
||||
|
||||
# Don't install the dependencies when we run `pod install` in the old architecture.
|
||||
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
||||
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
||||
s.pod_target_xcconfig = {
|
||||
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
||||
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
||||
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
||||
}
|
||||
s.dependency "React-Codegen"
|
||||
s.dependency "RCT-Folly"
|
||||
s.dependency "RCTRequired"
|
||||
s.dependency "RCTTypeSafety"
|
||||
s.dependency "ReactCommon/turbomodule/core"
|
||||
end
|
||||
end
|
||||
end
|
22
examples/react-native-video-plugin-sample/src/index.tsx
Normal file
22
examples/react-native-video-plugin-sample/src/index.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
|
||||
const LINKING_ERROR =
|
||||
`The package 'react-native-video-plugin-sample' doesn't seem to be linked. Make sure: \n\n` +
|
||||
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
||||
'- You rebuilt the app after installing the package\n' +
|
||||
'- You are not using Expo Go\n';
|
||||
|
||||
const VideoPluginSample = NativeModules.VideoPluginSample
|
||||
? NativeModules.VideoPluginSample
|
||||
: new Proxy(
|
||||
{},
|
||||
{
|
||||
get() {
|
||||
throw new Error(LINKING_ERROR);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export function multiply(a: number, b: number): Promise<number> {
|
||||
return VideoPluginSample.multiply(a, b);
|
||||
}
|
@ -81,6 +81,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
}
|
||||
}
|
||||
|
||||
private let instanceId = UUID().uuidString
|
||||
|
||||
private var _isBuffering = false {
|
||||
didSet {
|
||||
onVideoBuffer?(["isBuffering": _isBuffering, "target": reactTag as Any])
|
||||
@ -184,6 +186,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
|
||||
init(eventDispatcher: RCTEventDispatcher!) {
|
||||
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
||||
ReactNativeVideoManager.shared.registerView(newInstance: self)
|
||||
#if USE_GOOGLE_IMA
|
||||
_imaAdsManager = RCTIMAAdsManager(video: self, pipEnabled: isPipEnabled)
|
||||
#endif
|
||||
@ -263,6 +266,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
#if os(iOS)
|
||||
_pip = nil
|
||||
#endif
|
||||
ReactNativeVideoManager.shared.unregisterView(newInstance: self)
|
||||
}
|
||||
|
||||
// MARK: - App lifecycle handlers
|
||||
@ -462,6 +466,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
|
||||
if _player == nil {
|
||||
_player = AVPlayer()
|
||||
ReactNativeVideoManager.shared.onInstanceCreated(id: instanceId, player: _player)
|
||||
|
||||
_player!.replaceCurrentItem(with: playerItem)
|
||||
|
||||
if _showNotificationControls {
|
||||
@ -1261,6 +1267,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
_selectedAudioTrackCriteria = nil
|
||||
_presentingViewController = nil
|
||||
|
||||
ReactNativeVideoManager.shared.onInstanceRemoved(id: instanceId, player: _player)
|
||||
_player = nil
|
||||
_resouceLoaderDelegate = nil
|
||||
_playerObserver.clearPlayer()
|
||||
|
23
ios/Video/RNVPlugin.swift
Normal file
23
ios/Video/RNVPlugin.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// RNVPlugin.swift
|
||||
// react-native-video
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol RNVPlugin {
|
||||
/**
|
||||
* Function called when a new player is created
|
||||
* @param id: a random string identifying the player
|
||||
* @param player: the instantiated player reference
|
||||
*/
|
||||
func onInstanceCreated(id: String, player: Any)
|
||||
/**
|
||||
* Function called when a player should be destroyed
|
||||
* when this callback is called, the plugin shall free all
|
||||
* resources and release all reference to Player object
|
||||
* @param id: a random string identifying the player
|
||||
* @param player: the player to release
|
||||
*/
|
||||
func onInstanceRemoved(id: String, player: Any)
|
||||
}
|
53
ios/Video/ReactNativeVideoManager.swift
Normal file
53
ios/Video/ReactNativeVideoManager.swift
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// ReactNativeVideoManager.swift
|
||||
// react-native-video
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ReactNativeVideoManager: RNVPlugin {
|
||||
private let expectedMaxVideoCount = 10
|
||||
|
||||
// create a private initializer
|
||||
private init() {}
|
||||
|
||||
public static let shared: ReactNativeVideoManager = .init()
|
||||
|
||||
var instanceList: [RCTVideo] = Array()
|
||||
var pluginList: [RNVPlugin] = Array()
|
||||
|
||||
/**
|
||||
* register a new ReactExoplayerViewManager in the managed list
|
||||
*/
|
||||
func registerView(newInstance: RCTVideo) {
|
||||
if instanceList.count > expectedMaxVideoCount {
|
||||
DebugLog("multiple Video displayed ?")
|
||||
}
|
||||
instanceList.append(newInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister existing ReactExoplayerViewManager in the managed list
|
||||
*/
|
||||
func unregisterView(newInstance: RCTVideo) {
|
||||
if let i = instanceList.firstIndex(of: newInstance) {
|
||||
instanceList.remove(at: i)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* register a new plugin in the managed list
|
||||
*/
|
||||
public func registerPlugin(plugin: RNVPlugin) {
|
||||
pluginList.append(plugin)
|
||||
return
|
||||
}
|
||||
|
||||
public func onInstanceCreated(id: String, player: Any) {
|
||||
pluginList.forEach { it in it.onInstanceCreated(id: id, player: player) }
|
||||
}
|
||||
|
||||
public func onInstanceRemoved(id: String, player: Any) {
|
||||
pluginList.forEach { it in it.onInstanceRemoved(id: id, player: player) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user