bitmovin-player-react-native 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RNBitmovinPlayer.podspec +1 -1
- package/android/build.gradle +1 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/AnalyticsModule.kt +43 -11
- package/android/src/main/java/com/bitmovin/player/reactnative/OfflineModule.kt +279 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +37 -1
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +1 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +123 -35
- package/android/src/main/java/com/bitmovin/player/reactnative/offline/OfflineContentManagerBridge.kt +216 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/offline/OfflineDownloadRequest.kt +7 -0
- package/ios/DrmModule.swift +5 -5
- package/ios/OfflineContentManagerBridge.swift +141 -0
- package/ios/OfflineModule.m +19 -0
- package/ios/OfflineModule.swift +465 -0
- package/ios/PlayerModule.m +2 -0
- package/ios/PlayerModule.swift +40 -7
- package/ios/RCTConvert+BitmovinPlayer.swift +135 -1
- package/ios/RNBitmovinPlayer.h +1 -0
- package/lib/index.d.mts +382 -2
- package/lib/index.d.ts +382 -2
- package/lib/index.js +233 -0
- package/lib/index.mjs +231 -0
- package/package.json +1 -1
- package/src/adaptationConfig.ts +10 -0
- package/src/index.ts +2 -0
- package/src/offline/index.ts +7 -0
- package/src/offline/offlineContentConfig.ts +18 -0
- package/src/offline/offlineContentManager.ts +216 -0
- package/src/offline/offlineContentManagerListener.ts +187 -0
- package/src/offline/offlineContentOptions.ts +29 -0
- package/src/offline/offlineDownloadRequest.ts +20 -0
- package/src/offline/offlineSourceOptions.ts +11 -0
- package/src/offline/offlineState.ts +22 -0
- package/src/player.ts +30 -0
- package/src/source.ts +38 -0
package/RNBitmovinPlayer.podspec
CHANGED
|
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
20
20
|
|
|
21
21
|
s.dependency "React-Core"
|
|
22
|
-
s.dependency "BitmovinPlayer", "3.
|
|
22
|
+
s.dependency "BitmovinPlayer", "3.44.1"
|
|
23
23
|
s.ios.dependency "GoogleAds-IMA-iOS-SDK", "3.18.4"
|
|
24
24
|
s.tvos.dependency "GoogleAds-IMA-tvOS-SDK", "4.8.2"
|
|
25
25
|
end
|
package/android/build.gradle
CHANGED
|
@@ -53,8 +53,7 @@ dependencies {
|
|
|
53
53
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
|
54
54
|
implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.29.0'
|
|
55
55
|
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
|
|
56
|
-
implementation 'com.bitmovin.
|
|
57
|
-
implementation 'com.bitmovin.player:player:3.40.0'
|
|
56
|
+
implementation 'com.bitmovin.player:player:3.42.0'
|
|
58
57
|
//noinspection GradleDynamicVersion
|
|
59
58
|
implementation 'com.facebook.react:react-native:+' // From node_modules
|
|
60
59
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.bitmovin.player.reactnative
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.bitmovin.analytics.bitmovin.player.api.IBitmovinPlayerCollector
|
|
4
5
|
import com.bitmovin.player.reactnative.converter.JsonConverter
|
|
5
6
|
import com.facebook.react.bridge.*
|
|
6
7
|
import com.facebook.react.module.annotations.ReactModule
|
|
@@ -13,7 +14,7 @@ class AnalyticsModule(private val context: ReactApplicationContext) : ReactConte
|
|
|
13
14
|
/**
|
|
14
15
|
* In-memory mapping from `nativeId`s to `BitmovinPlayerCollector` instances.
|
|
15
16
|
*/
|
|
16
|
-
private val collectors: Registry<
|
|
17
|
+
private val collectors: Registry<IBitmovinPlayerCollector> = mutableMapOf()
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* JS exported module name.
|
|
@@ -25,7 +26,7 @@ class AnalyticsModule(private val context: ReactApplicationContext) : ReactConte
|
|
|
25
26
|
* @param nativeId `BitmovinPlayerCollector` instance ID.
|
|
26
27
|
* @return The associated `BitmovinPlayerCollector` instance or `null`.
|
|
27
28
|
*/
|
|
28
|
-
fun getCollector(nativeId: NativeId?):
|
|
29
|
+
fun getCollector(nativeId: NativeId?): IBitmovinPlayerCollector? {
|
|
29
30
|
if (nativeId == null) {
|
|
30
31
|
return null
|
|
31
32
|
}
|
|
@@ -40,7 +41,7 @@ class AnalyticsModule(private val context: ReactApplicationContext) : ReactConte
|
|
|
40
41
|
fun initWithConfig(nativeId: NativeId, config: ReadableMap?) {
|
|
41
42
|
uiManager()?.addUIBlock { _ ->
|
|
42
43
|
JsonConverter.toAnalyticsConfig(config)?.let {
|
|
43
|
-
collectors[nativeId] =
|
|
44
|
+
collectors[nativeId] = IBitmovinPlayerCollector.create(it, context)
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -106,8 +107,20 @@ class AnalyticsModule(private val context: ReactApplicationContext) : ReactConte
|
|
|
106
107
|
@ReactMethod
|
|
107
108
|
fun setCustomData(nativeId: NativeId, playerId: NativeId?, json: ReadableMap?) {
|
|
108
109
|
uiManager()?.addUIBlock { _ ->
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
val source = playerModule()?.getPlayer(playerId)?.source
|
|
111
|
+
val collector = collectors[nativeId]
|
|
112
|
+
val customData = JsonConverter.toAnalyticsCustomData(json)
|
|
113
|
+
when {
|
|
114
|
+
source == null -> Log.d(
|
|
115
|
+
"[AnalyticsModule]", "Could not find source for player ($playerId)"
|
|
116
|
+
)
|
|
117
|
+
collector == null -> Log.d(
|
|
118
|
+
"[AnalyticsModule]", "Could not find analytics collector ($nativeId)"
|
|
119
|
+
)
|
|
120
|
+
customData == null -> Log.d(
|
|
121
|
+
"[AnalyticsModule]", "Could not convert custom data, thus they are not applied to the active source for the player ($playerId) with the collector ($nativeId)"
|
|
122
|
+
)
|
|
123
|
+
else -> collector.setCustomData(source, customData)
|
|
111
124
|
}
|
|
112
125
|
}
|
|
113
126
|
}
|
|
@@ -120,8 +133,16 @@ class AnalyticsModule(private val context: ReactApplicationContext) : ReactConte
|
|
|
120
133
|
@ReactMethod
|
|
121
134
|
fun getCustomData(nativeId: NativeId, playerId: NativeId?, promise: Promise) {
|
|
122
135
|
uiManager()?.addUIBlock { _ ->
|
|
123
|
-
|
|
124
|
-
|
|
136
|
+
val source = playerModule()?.getPlayer(playerId)?.source
|
|
137
|
+
val collector = collectors[nativeId]
|
|
138
|
+
when {
|
|
139
|
+
source == null -> promise.reject(
|
|
140
|
+
"[AnalyticsModule]", "Could not find source for player ($playerId)"
|
|
141
|
+
)
|
|
142
|
+
collector == null -> promise.reject(
|
|
143
|
+
"[AnalyticsModule]", "Could not find analytics collector ($nativeId)"
|
|
144
|
+
)
|
|
145
|
+
else -> promise.resolve(JsonConverter.fromAnalyticsCustomData(collector.getCustomData(source)))
|
|
125
146
|
}
|
|
126
147
|
}
|
|
127
148
|
}
|
|
@@ -129,9 +150,20 @@ class AnalyticsModule(private val context: ReactApplicationContext) : ReactConte
|
|
|
129
150
|
@ReactMethod
|
|
130
151
|
fun addSourceMetadata(nativeId: NativeId, playerId: NativeId?, json: ReadableMap?) {
|
|
131
152
|
uiManager()?.addUIBlock { _ ->
|
|
132
|
-
val
|
|
133
|
-
|
|
134
|
-
|
|
153
|
+
val source = playerModule()?.getPlayer(playerId)?.source
|
|
154
|
+
val collector = collectors[nativeId]
|
|
155
|
+
val sourceMetadata = JsonConverter.toAnalyticsSourceMetadata(json)
|
|
156
|
+
when {
|
|
157
|
+
source == null -> Log.d(
|
|
158
|
+
"[AnalyticsModule]", "Could not find source for player ($playerId)"
|
|
159
|
+
)
|
|
160
|
+
collector == null -> Log.d(
|
|
161
|
+
"[AnalyticsModule]", "Could not find analytics collector ($nativeId)"
|
|
162
|
+
)
|
|
163
|
+
sourceMetadata == null -> Log.d(
|
|
164
|
+
"[AnalyticsModule]", "Could not convert source metadata, thus they are not applied to the collector ($nativeId)"
|
|
165
|
+
)
|
|
166
|
+
else -> collector.addSourceMetadata(source, sourceMetadata)
|
|
135
167
|
}
|
|
136
168
|
}
|
|
137
169
|
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
package com.bitmovin.player.reactnative
|
|
2
|
+
|
|
3
|
+
import com.bitmovin.player.api.offline.options.OfflineOptionEntryState
|
|
4
|
+
import com.bitmovin.player.reactnative.converter.JsonConverter
|
|
5
|
+
import com.bitmovin.player.reactnative.extensions.toList
|
|
6
|
+
import com.bitmovin.player.reactnative.offline.OfflineDownloadRequest
|
|
7
|
+
import com.bitmovin.player.reactnative.offline.OfflineContentManagerBridge
|
|
8
|
+
import com.facebook.react.bridge.*
|
|
9
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
10
|
+
import com.facebook.react.uimanager.UIManagerModule
|
|
11
|
+
|
|
12
|
+
private const val OFFLINE_MODULE = "BitmovinOfflineModule"
|
|
13
|
+
|
|
14
|
+
@ReactModule(name = OFFLINE_MODULE)
|
|
15
|
+
class OfflineModule(private val context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* In-memory mapping from `nativeId`s to `OfflineManager` instances.
|
|
19
|
+
*/
|
|
20
|
+
private val offlineContentManagerBridges: Registry<OfflineContentManagerBridge> = mutableMapOf()
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* JS exported module name.
|
|
24
|
+
*/
|
|
25
|
+
override fun getName() = OFFLINE_MODULE
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Fetches the `OfflineManager` instance associated with `nativeId` from the internal offline managers.
|
|
29
|
+
* @param nativeId `OfflineManager` instance ID.
|
|
30
|
+
* @return The associated `OfflineManager` instance or `null`.
|
|
31
|
+
*/
|
|
32
|
+
fun getOfflineContentManagerBridge(nativeId: NativeId?): OfflineContentManagerBridge? {
|
|
33
|
+
if (nativeId == null) {
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
return offlineContentManagerBridges[nativeId]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Callback when a new NativeEventEmitter is created from the Typescript layer.
|
|
41
|
+
*/
|
|
42
|
+
@ReactMethod
|
|
43
|
+
fun addListener(eventName: String?) {
|
|
44
|
+
// NO-OP
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Callback when a NativeEventEmitter is removed from the Typescript layer.
|
|
49
|
+
*/
|
|
50
|
+
@ReactMethod
|
|
51
|
+
fun removeListeners(count: Int?) {
|
|
52
|
+
// NO-OP
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new `OfflineManager` instance inside the internal offline managers using the provided `config` object.
|
|
57
|
+
* @param config `ReadableMap` object received from JS. Should contain a sourceConfig and location.
|
|
58
|
+
*/
|
|
59
|
+
@ReactMethod
|
|
60
|
+
fun initWithConfig(nativeId: NativeId, config: ReadableMap?, drmNativeId: NativeId?, promise: Promise) {
|
|
61
|
+
uiManager()?.addUIBlock {
|
|
62
|
+
if (!offlineContentManagerBridges.containsKey(nativeId)) {
|
|
63
|
+
val identifier = config?.getString("identifier")
|
|
64
|
+
val sourceConfig = JsonConverter.toSourceConfig(config?.getMap("sourceConfig"))
|
|
65
|
+
sourceConfig?.drmConfig = drmModule()?.getConfig(drmNativeId)
|
|
66
|
+
|
|
67
|
+
if (identifier.isNullOrEmpty() || sourceConfig == null) {
|
|
68
|
+
promise.reject(IllegalArgumentException("Identifier and SourceConfig may not be null"))
|
|
69
|
+
return@addUIBlock
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
offlineContentManagerBridges[nativeId] = OfflineContentManagerBridge(nativeId, context, identifier, sourceConfig, context.cacheDir.path)
|
|
73
|
+
}
|
|
74
|
+
promise.resolve(null)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@ReactMethod
|
|
79
|
+
fun getState(nativeId: NativeId, promise: Promise) {
|
|
80
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
81
|
+
promise.resolve(state.name)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Starts the `OfflineContentManager`'s asynchronous process of fetching the `OfflineContentOptions`.
|
|
87
|
+
* When the options are loaded a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onOptionsAvailable`.
|
|
88
|
+
* @param nativeId Target offline manager.
|
|
89
|
+
*/
|
|
90
|
+
@ReactMethod
|
|
91
|
+
fun getOptions(nativeId: NativeId, promise: Promise) {
|
|
92
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
93
|
+
getOptions()
|
|
94
|
+
promise.resolve(null)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Enqueues downloads according to the `OfflineDownloadRequest`.
|
|
100
|
+
* The promise will reject in the event of null or invalid request parameters.
|
|
101
|
+
* The promise will reject an `IllegalOperationException` when selecting an `OfflineOptionEntry` to download that is not compatible with the current state.
|
|
102
|
+
* @param nativeId Target offline manager.
|
|
103
|
+
* @param request `ReadableMap` that contains the `OfflineManager.OfflineOptionType`, id, and `OfflineOptionEntryAction` necessary to set the new action.
|
|
104
|
+
*/
|
|
105
|
+
@ReactMethod
|
|
106
|
+
fun download(nativeId: NativeId, request: ReadableMap?, promise: Promise) {
|
|
107
|
+
if (request == null) {
|
|
108
|
+
promise.reject(IllegalArgumentException("Request may not be null"))
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
113
|
+
try {
|
|
114
|
+
when (state) {
|
|
115
|
+
OfflineOptionEntryState.Downloaded -> {
|
|
116
|
+
promise.reject(IllegalStateException("Download already completed"))
|
|
117
|
+
return@safeOfflineContentManager
|
|
118
|
+
}
|
|
119
|
+
OfflineOptionEntryState.Downloading,
|
|
120
|
+
OfflineOptionEntryState.Failed -> {
|
|
121
|
+
promise.reject(IllegalStateException("Download already in progress"))
|
|
122
|
+
return@safeOfflineContentManager
|
|
123
|
+
}
|
|
124
|
+
OfflineOptionEntryState.Suspended -> {
|
|
125
|
+
promise.reject(IllegalStateException("Download is suspended"))
|
|
126
|
+
return@safeOfflineContentManager
|
|
127
|
+
}
|
|
128
|
+
else -> {}
|
|
129
|
+
}
|
|
130
|
+
val minimumBitRate = if(request.hasKey("minimumBitrate")) request.getInt("minimumBitrate") else null
|
|
131
|
+
if (minimumBitRate != null && minimumBitRate < 0) {
|
|
132
|
+
promise.reject(IllegalArgumentException("Invalid download request"))
|
|
133
|
+
return@safeOfflineContentManager
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
val audioOptionIds = request.getArray("audioOptionIds")?.toList<String>()?.filterNotNull()
|
|
137
|
+
val textOptionIds = request.getArray("textOptionIds")?.toList<String>()?.filterNotNull()
|
|
138
|
+
|
|
139
|
+
getOfflineContentManagerBridge(nativeId)?.process(OfflineDownloadRequest(minimumBitRate, audioOptionIds, textOptionIds))
|
|
140
|
+
promise.resolve(null)
|
|
141
|
+
} catch (e: Exception) {
|
|
142
|
+
promise.reject(e)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Resumes all suspended actions.
|
|
149
|
+
* @param nativeId Target offline manager.
|
|
150
|
+
*/
|
|
151
|
+
@ReactMethod
|
|
152
|
+
fun resume(nativeId: NativeId, promise: Promise) {
|
|
153
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
154
|
+
resume()
|
|
155
|
+
promise.resolve(null)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Suspends all active actions.
|
|
161
|
+
* @param nativeId Target offline manager.
|
|
162
|
+
*/
|
|
163
|
+
@ReactMethod
|
|
164
|
+
fun suspend(nativeId: NativeId, promise: Promise) {
|
|
165
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
166
|
+
suspend()
|
|
167
|
+
promise.resolve(null)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Cancels and deletes the current download.
|
|
173
|
+
* @param nativeId Target offline manager.
|
|
174
|
+
*/
|
|
175
|
+
@ReactMethod
|
|
176
|
+
fun cancelDownload(nativeId: NativeId, promise: Promise) {
|
|
177
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
178
|
+
cancelDownload()
|
|
179
|
+
promise.resolve(null)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Resolve `nativeId`'s current `usedStorage`.
|
|
185
|
+
* @param nativeId Target offline manager.
|
|
186
|
+
*/
|
|
187
|
+
@ReactMethod
|
|
188
|
+
fun usedStorage(nativeId: NativeId, promise: Promise) {
|
|
189
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
190
|
+
promise.resolve(offlineContentManager.usedStorage.toDouble())
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Deletes everything related to the related content ID.
|
|
196
|
+
* @param nativeId Target offline manager.
|
|
197
|
+
*/
|
|
198
|
+
@ReactMethod
|
|
199
|
+
fun deleteAll(nativeId: NativeId, promise: Promise) {
|
|
200
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
201
|
+
deleteAll()
|
|
202
|
+
promise.resolve(null)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Downloads the offline license.
|
|
208
|
+
* When finished successfully a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onDrmLicenseUpdated`.
|
|
209
|
+
* Errors are transmitted by a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onError`.
|
|
210
|
+
* @param nativeId Target offline manager.
|
|
211
|
+
*/
|
|
212
|
+
@ReactMethod
|
|
213
|
+
fun downloadLicense(nativeId: NativeId, promise: Promise) {
|
|
214
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
215
|
+
downloadLicense()
|
|
216
|
+
promise.resolve(null)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Releases the currently held offline license.
|
|
222
|
+
* When finished successfully a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onDrmLicenseUpdated`.
|
|
223
|
+
* Errors are transmitted by a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onError`.
|
|
224
|
+
* @param nativeId Target offline manager.
|
|
225
|
+
*/
|
|
226
|
+
@ReactMethod
|
|
227
|
+
fun releaseLicense(nativeId: NativeId, promise: Promise) {
|
|
228
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
229
|
+
releaseLicense()
|
|
230
|
+
promise.resolve(null)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Renews the already downloaded DRM license.
|
|
236
|
+
* When finished successfully a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onDrmLicenseUpdated`.
|
|
237
|
+
* Errors are transmitted by a device event will be fired where the event type is `BitmovinOfflineEvent` and the data has an event type of `onError`.
|
|
238
|
+
* @param nativeId Target offline manager.
|
|
239
|
+
*/
|
|
240
|
+
@ReactMethod
|
|
241
|
+
fun renewOfflineLicense(nativeId: NativeId, promise: Promise) {
|
|
242
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
243
|
+
renewOfflineLicense()
|
|
244
|
+
promise.resolve(null)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Call `.release()` on `nativeId`'s offline manager.
|
|
250
|
+
* IMPORTANT: Call this when the component, in which it was created, is destroyed.
|
|
251
|
+
* The `OfflineManager` should not be used after calling this method.
|
|
252
|
+
* @param nativeId Target player Id.
|
|
253
|
+
*/
|
|
254
|
+
@ReactMethod
|
|
255
|
+
fun release(nativeId: NativeId, promise: Promise) {
|
|
256
|
+
safeOfflineContentManager(nativeId, promise) {
|
|
257
|
+
release()
|
|
258
|
+
offlineContentManagerBridges.remove(nativeId)
|
|
259
|
+
promise.resolve(null)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private fun safeOfflineContentManager(nativeId: NativeId, promise: Promise, runBlock: OfflineContentManagerBridge.() -> Unit) {
|
|
264
|
+
getOfflineContentManagerBridge(nativeId)?.let(runBlock)
|
|
265
|
+
?: promise.reject(IllegalArgumentException("Could not find the offline module instance"))
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Helper function that returns the initialized `DrmModule` instance.
|
|
270
|
+
*/
|
|
271
|
+
private fun drmModule(): DrmModule? =
|
|
272
|
+
context.getNativeModule(DrmModule::class.java)
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Helper function that returns the initialized `UIManager` instance.
|
|
276
|
+
*/
|
|
277
|
+
private fun uiManager(): UIManagerModule? =
|
|
278
|
+
context.getNativeModule(UIManagerModule::class.java)
|
|
279
|
+
}
|
|
@@ -50,7 +50,7 @@ class PlayerModule(private val context: ReactApplicationContext) : ReactContextB
|
|
|
50
50
|
/**
|
|
51
51
|
* Load the source of the given `nativeId` with `config` options from JS.
|
|
52
52
|
* @param nativeId Target player.
|
|
53
|
-
* @param
|
|
53
|
+
* @param sourceNativeId Target source.
|
|
54
54
|
*/
|
|
55
55
|
@ReactMethod
|
|
56
56
|
fun loadSource(nativeId: NativeId, sourceNativeId: String) {
|
|
@@ -61,6 +61,24 @@ class PlayerModule(private val context: ReactApplicationContext) : ReactContextB
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Load the `offlineSourceConfig` for the player with `nativeId` and offline source module with `offlineModuleNativeId`.
|
|
66
|
+
* @param nativeId Target player.
|
|
67
|
+
* @param offlineContentManagerBridgeId Target offline module.
|
|
68
|
+
* @param options Source configuration options from JS.
|
|
69
|
+
*/
|
|
70
|
+
@ReactMethod
|
|
71
|
+
fun loadOfflineContent(nativeId: NativeId, offlineContentManagerBridgeId: String, options: ReadableMap?) {
|
|
72
|
+
uiManager()?.addUIBlock {
|
|
73
|
+
val offlineSourceConfig = offlineModule()?.getOfflineContentManagerBridge(offlineContentManagerBridgeId)
|
|
74
|
+
?.offlineContentManager?.offlineSourceConfig
|
|
75
|
+
|
|
76
|
+
if (offlineSourceConfig != null) {
|
|
77
|
+
players[nativeId]?.load(offlineSourceConfig)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
/**
|
|
65
83
|
* Call `.unload()` on `nativeId`'s player.
|
|
66
84
|
* @param nativeId Target player Id.
|
|
@@ -398,6 +416,18 @@ class PlayerModule(private val context: ReactApplicationContext) : ReactContextB
|
|
|
398
416
|
}
|
|
399
417
|
}
|
|
400
418
|
|
|
419
|
+
/**
|
|
420
|
+
* Sets the max selectable bitrate for the player.
|
|
421
|
+
* @param nativeId Target player id.
|
|
422
|
+
* @param maxSelectableBitrate The desired max bitrate limit.
|
|
423
|
+
*/
|
|
424
|
+
@ReactMethod
|
|
425
|
+
fun setMaxSelectableBitrate(nativeId: NativeId, maxSelectableBitrate: Int) {
|
|
426
|
+
uiManager()?.addUIBlock {
|
|
427
|
+
players[nativeId]?.setMaxSelectableVideoBitrate(maxSelectableBitrate.takeUnless { it == -1 } ?: Integer.MAX_VALUE)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
401
431
|
/**
|
|
402
432
|
* Helper function that returns the initialized `UIManager` instance.
|
|
403
433
|
*/
|
|
@@ -409,4 +439,10 @@ class PlayerModule(private val context: ReactApplicationContext) : ReactContextB
|
|
|
409
439
|
*/
|
|
410
440
|
private fun sourceModule(): SourceModule? =
|
|
411
441
|
context.getNativeModule(SourceModule::class.java)
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Helper function that returns the initialized `OfflineModule` instance.
|
|
445
|
+
*/
|
|
446
|
+
private fun offlineModule(): OfflineModule? =
|
|
447
|
+
context.getNativeModule(OfflineModule::class.java)
|
|
412
448
|
}
|
|
@@ -19,6 +19,7 @@ class RNPlayerViewPackage : ReactPackage {
|
|
|
19
19
|
*/
|
|
20
20
|
override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
|
|
21
21
|
return mutableListOf(
|
|
22
|
+
OfflineModule(reactContext),
|
|
22
23
|
UuidModule(reactContext),
|
|
23
24
|
PlayerModule(reactContext),
|
|
24
25
|
SourceModule(reactContext),
|