@takeoffmedia/react-native-penthera 0.2.66 → 0.3.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/android/src/main/java/com/takeoffmediareactnativepenthera/AssetQueueObserver.kt +117 -94
- package/android/src/main/java/com/takeoffmediareactnativepenthera/EventEmitter.kt +23 -12
- package/android/src/main/java/com/takeoffmediareactnativepenthera/PentheraModule.kt +55 -39
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/DemoLicenseManager.kt +0 -14
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/OfflineVideoEngine.kt +236 -174
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/data/Item.kt +0 -18
- package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/notification/NotificationFactory.kt +11 -8
- package/android/src/main/res/values/colors.xml +1 -0
- package/lib/commonjs/hooks/usePenthera/usePentheraInit.js +69 -0
- package/lib/commonjs/hooks/usePenthera/usePentheraInit.js.map +1 -1
- package/lib/commonjs/nativeModules/index.js +8 -0
- package/lib/commonjs/nativeModules/index.js.map +1 -1
- package/lib/module/hooks/usePenthera/usePentheraInit.js +68 -0
- package/lib/module/hooks/usePenthera/usePentheraInit.js.map +1 -1
- package/lib/module/nativeModules/index.js +6 -0
- package/lib/module/nativeModules/index.js.map +1 -1
- package/lib/typescript/hooks/usePenthera/usePentheraInit.d.ts +5 -0
- package/lib/typescript/hooks/usePenthera/usePentheraInit.d.ts.map +1 -1
- package/lib/typescript/nativeModules/index.d.ts +2 -0
- package/lib/typescript/nativeModules/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/hooks/usePenthera/usePentheraInit.tsx +70 -0
- package/src/nativeModules/index.ts +8 -0
package/android/src/main/java/com/takeoffmediareactnativepenthera/virtuoso/OfflineVideoEngine.kt
CHANGED
|
@@ -1,118 +1,110 @@
|
|
|
1
1
|
package com.takeoffmediareactnativepenthera.virtuoso
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
-
import android.app.Activity
|
|
5
4
|
import android.content.Context
|
|
6
5
|
import android.util.Log
|
|
7
|
-
import com.bitmovin.player.api.media.subtitle.SubtitleTrack
|
|
8
6
|
import com.bitmovin.player.reactnative.PlayerModule
|
|
9
7
|
import com.bitmovin.player.reactnative.converter.JsonConverter
|
|
10
|
-
|
|
8
|
+
import com.facebook.react.bridge.Arguments
|
|
9
|
+
import com.facebook.react.bridge.Promise
|
|
11
10
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
11
|
+
import com.facebook.react.bridge.ReadableArray
|
|
12
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
12
13
|
import com.google.gson.Gson
|
|
13
|
-
import com.penthera.
|
|
14
|
+
import com.penthera.virtuososdk.client.AncillaryFile
|
|
14
15
|
import com.penthera.virtuososdk.client.EngineObserver
|
|
15
16
|
import com.penthera.virtuososdk.client.IAsset
|
|
16
17
|
import com.penthera.virtuososdk.client.IIdentifier
|
|
17
18
|
import com.penthera.virtuososdk.client.IPushRegistrationObserver
|
|
18
19
|
import com.penthera.virtuososdk.client.ISegmentedAsset
|
|
19
20
|
import com.penthera.virtuososdk.client.ISegmentedAssetFromParserObserver
|
|
20
|
-
import com.penthera.virtuososdk.client.Observers
|
|
21
21
|
import com.penthera.virtuososdk.client.Virtuoso
|
|
22
22
|
import com.penthera.virtuososdk.client.bitmovin.BitmovinSourceManager
|
|
23
23
|
import com.penthera.virtuososdk.client.builders.MPDAssetBuilder
|
|
24
24
|
import com.penthera.virtuososdk.interfaces.toolkit.VirtuosoSegmentedFile
|
|
25
25
|
import com.takeoffmediareactnativepenthera.AssetQueueObserver
|
|
26
|
-
import java.net.URL
|
|
27
|
-
import com.facebook.react.bridge.Arguments
|
|
28
|
-
import com.facebook.react.uimanager.UIManagerModule
|
|
29
|
-
import com.facebook.react.bridge.Promise
|
|
30
|
-
import com.facebook.react.bridge.ReadableArray
|
|
31
|
-
import com.penthera.virtuososdk.client.AncillaryFile
|
|
32
26
|
import okhttp3.OkHttpClient
|
|
33
27
|
import okhttp3.Request
|
|
34
28
|
import org.json.JSONArray
|
|
35
29
|
import org.json.JSONObject
|
|
36
30
|
import java.io.IOException
|
|
37
|
-
import java.net.
|
|
31
|
+
import java.net.MalformedURLException
|
|
32
|
+
import java.net.URL
|
|
38
33
|
import java.text.SimpleDateFormat
|
|
39
34
|
import java.util.Calendar
|
|
35
|
+
import com.penthera.common.Common
|
|
36
|
+
import com.penthera.virtuososdk.client.IService
|
|
37
|
+
import com.takeoffmediareactnativepenthera.EventEmitter
|
|
38
|
+
import com.takeoffmediareactnativepenthera.PentheraEvent
|
|
39
|
+
import com.takeoffmediareactnativepenthera.virtuoso.errors.PentheraErrors
|
|
40
40
|
|
|
41
41
|
class OfflineVideoEngine(private val context: ReactApplicationContext) {
|
|
42
|
-
|
|
43
|
-
private
|
|
42
|
+
private val virtuoso = Virtuoso(context)
|
|
43
|
+
private var queueObserver = AssetQueueObserver(this, virtuoso)
|
|
44
44
|
var asset: IAsset? = null
|
|
45
|
-
|
|
45
|
+
val assetId: MutableList<String> = mutableListOf()
|
|
46
46
|
private val gson = Gson()
|
|
47
|
-
var minimumLowBandWidth: Double = 0.00010
|
|
48
|
-
var valueUserId: String = ""
|
|
49
|
-
var valueBackPlaneUrl: String = ""
|
|
50
|
-
var valuePublicKey: String = ""
|
|
51
|
-
var valuePrivateKey: String = ""
|
|
52
47
|
private val client = OkHttpClient()
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
var minimumLowBandWidth: Double = 0.5 // 500kbps
|
|
49
|
+
val mService: IService = virtuoso.service
|
|
50
|
+
private val enginePauseObserver = object: EngineObserver() {
|
|
55
51
|
override fun engineStatusChanged(status: Int) {
|
|
56
52
|
Log.e("MiModulo", "<<<<<<<<<<status $status>>>>>>>>>>>>")
|
|
57
53
|
}
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
private fun getInstanceVirtuoso(): Virtuoso {
|
|
61
|
-
virtuoso = Virtuoso(context)
|
|
62
|
-
queueObserver = AssetQueueObserver(this, virtuoso)
|
|
63
|
-
onResume()
|
|
64
|
-
return virtuoso
|
|
65
|
-
}
|
|
66
|
-
|
|
67
56
|
fun onResume() {
|
|
68
|
-
virtuoso.
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
virtuoso.let {
|
|
58
|
+
it.onResume()
|
|
59
|
+
it.addObserver(queueObserver)
|
|
60
|
+
it.addObserver(enginePauseObserver)
|
|
61
|
+
mService.bind()
|
|
62
|
+
}
|
|
71
63
|
}
|
|
72
64
|
|
|
73
65
|
fun onPause() {
|
|
74
|
-
virtuoso.
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
virtuoso.let {
|
|
67
|
+
it.onPause()
|
|
68
|
+
it.removeObserver(queueObserver)
|
|
69
|
+
it.removeObserver(enginePauseObserver)
|
|
70
|
+
mService.unbind()
|
|
71
|
+
}
|
|
77
72
|
}
|
|
78
73
|
|
|
79
74
|
fun setup(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
override fun onServiceAvailabilityResponse(
|
|
102
|
-
pushService: Int,
|
|
103
|
-
errorCode: Int
|
|
104
|
-
) {
|
|
105
|
-
//callback for push registration. this will be detailed in subsequent tutorials
|
|
106
|
-
}
|
|
75
|
+
userId: String,
|
|
76
|
+
backplaneUrl: String,
|
|
77
|
+
publicKey: String,
|
|
78
|
+
privateKey: String,
|
|
79
|
+
promise: Promise
|
|
80
|
+
) {
|
|
81
|
+
try {
|
|
82
|
+
onResume()
|
|
83
|
+
virtuoso.settings.batteryThreshold = 0f
|
|
84
|
+
virtuoso.startup(
|
|
85
|
+
URL(backplaneUrl),
|
|
86
|
+
userId,
|
|
87
|
+
android.os.Build.MODEL,
|
|
88
|
+
publicKey,
|
|
89
|
+
privateKey,
|
|
90
|
+
object : IPushRegistrationObserver {
|
|
91
|
+
override fun onServiceAvailabilityResponse(
|
|
92
|
+
pushService: Int,
|
|
93
|
+
errorCode: Int
|
|
94
|
+
) {
|
|
95
|
+
//callback for push registration. this will be detailed in subsequent tutorials
|
|
107
96
|
}
|
|
108
|
-
).let {
|
|
109
|
-
promise?.resolve("Penthera initialization successfully")
|
|
110
97
|
}
|
|
111
|
-
|
|
98
|
+
).let {
|
|
99
|
+
promise.resolve("Penthera initialization successfully")
|
|
100
|
+
}
|
|
101
|
+
} catch (e: MalformedURLException) {
|
|
102
|
+
// Handle the exception here, for example, reject the promise
|
|
103
|
+
promise.reject(e)
|
|
104
|
+
}
|
|
112
105
|
}
|
|
113
106
|
|
|
114
107
|
fun downloadAsset(newItem: String) {
|
|
115
|
-
setup()
|
|
116
108
|
val data = JSONObject(newItem)
|
|
117
109
|
val item = data["item"] as JSONObject
|
|
118
110
|
assetId.add(item["id"].toString())
|
|
@@ -169,80 +161,100 @@ class OfflineVideoEngine(private val context: ReactApplicationContext) {
|
|
|
169
161
|
virtuoso.assetManager.createMPDSegmentedAssetAsync(params)
|
|
170
162
|
}
|
|
171
163
|
|
|
172
|
-
fun getDownloads(
|
|
164
|
+
fun getDownloads(promise: Promise) {
|
|
173
165
|
val completedList = mutableListOf<MutableMap<String, Any>>()
|
|
174
|
-
val cursor = virtuoso.assetManager
|
|
175
|
-
val count = cursor
|
|
176
|
-
if(
|
|
166
|
+
val cursor = virtuoso.assetManager.cursor
|
|
167
|
+
val count = cursor.count
|
|
168
|
+
if (count == 0) {
|
|
177
169
|
cursor.close()
|
|
178
|
-
return gson.toJson(completedList)
|
|
170
|
+
return promise.resolve(gson.toJson(completedList))
|
|
179
171
|
}
|
|
180
|
-
val columnNames = cursor
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
if (columnName == "eap") {
|
|
215
|
-
eap = value
|
|
216
|
-
}
|
|
217
|
-
if(columnName == "activePercentOfDownloads"){
|
|
218
|
-
val percentage = value.toDouble() * 100
|
|
219
|
-
val isComplete = percentage == 100.0
|
|
220
|
-
dataMap["isCompleted"] = isComplete
|
|
221
|
-
}
|
|
222
|
-
if (columnName == "firstPlayTime") {
|
|
223
|
-
var eadFormated = dateToString(ead)
|
|
224
|
-
var eapFormated = dateToString(eap)
|
|
225
|
-
dataMap["data"] = (dataMap["data"] as? MutableMap<String, Any> ?: mutableMapOf()).apply {
|
|
226
|
-
put("effectiveExpiryDate", if (value == "0") eadFormated else eapFormated)
|
|
172
|
+
val columnNames = cursor.columnNames
|
|
173
|
+
while (cursor.moveToNext() && columnNames != null) {
|
|
174
|
+
val dataMap = mutableMapOf<String, Any>()
|
|
175
|
+
var eap = ""
|
|
176
|
+
var ead = ""
|
|
177
|
+
for (columnName in columnNames) {
|
|
178
|
+
val columnIndex = cursor.getColumnIndex(columnName)
|
|
179
|
+
if (columnIndex >= 0) {
|
|
180
|
+
val value = cursor.getString(columnIndex)
|
|
181
|
+
if (columnName == "description") {
|
|
182
|
+
val jsonObject = Gson().fromJson(value, Map::class.java)
|
|
183
|
+
dataMap["data"] = jsonObject["data"] as Any
|
|
184
|
+
dataMap["title"] = jsonObject["title"] as Any
|
|
185
|
+
dataMap["thumbnails"] = jsonObject["thumbnails"] as Any
|
|
186
|
+
} else if (value != null) {
|
|
187
|
+
dataMap[columnName] = value
|
|
188
|
+
}
|
|
189
|
+
if (columnName == "assetId") {
|
|
190
|
+
dataMap["id"] = value
|
|
191
|
+
UiThreadUtil.runOnUiThread {
|
|
192
|
+
val list = virtuoso.assetManager.getByAssetId(value)
|
|
193
|
+
list.let {
|
|
194
|
+
if (it.isNotEmpty()) {
|
|
195
|
+
asset = list[0] as VirtuosoSegmentedFile
|
|
196
|
+
if (asset?.downloadStatus == Common.AssetStatus.DOWNLOAD_DENIED_COPIES) {
|
|
197
|
+
EventEmitter.sharedInstance.dispatch(
|
|
198
|
+
"penthera",
|
|
199
|
+
PentheraEvent.ERROR_DOWNLOAD,
|
|
200
|
+
value,
|
|
201
|
+
PentheraErrors.DOWNLOAD_DENIED_COPIES
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
227
205
|
}
|
|
228
206
|
}
|
|
229
207
|
}
|
|
208
|
+
if (columnName == "durationSeconds") {
|
|
209
|
+
(dataMap["data"] as? MutableMap<String, Any> ?: mutableMapOf()).apply {
|
|
210
|
+
put("duration", value)
|
|
211
|
+
}.also { dataMap["data"] = it }
|
|
212
|
+
}
|
|
213
|
+
if (columnName == "expectedSize") {
|
|
214
|
+
(dataMap["data"] as? MutableMap<String, Any> ?: mutableMapOf()).apply {
|
|
215
|
+
put("estimatedSize", value)
|
|
216
|
+
}.also { dataMap["data"] = it }
|
|
217
|
+
}
|
|
218
|
+
if (columnName == "ead") {
|
|
219
|
+
ead = value
|
|
220
|
+
}
|
|
221
|
+
if (columnName == "eap") {
|
|
222
|
+
eap = value
|
|
223
|
+
}
|
|
224
|
+
if (columnName == "activePercentOfDownloads") {
|
|
225
|
+
val percentage = value.toDouble() * 100
|
|
226
|
+
val isComplete = percentage == 100.0
|
|
227
|
+
dataMap["isCompleted"] = isComplete
|
|
228
|
+
}
|
|
229
|
+
if (columnName == "firstPlayTime") {
|
|
230
|
+
val eadFormated = dateToString(ead)
|
|
231
|
+
val eapFormated = dateToString(eap)
|
|
232
|
+
(dataMap["data"] as? MutableMap<String, Any> ?: mutableMapOf()).apply {
|
|
233
|
+
put("effectiveExpiryDate", if (value == "0") eadFormated else eapFormated)
|
|
234
|
+
}.also { dataMap["data"] = it }
|
|
235
|
+
}
|
|
230
236
|
}
|
|
231
|
-
dataMap["isPaused"] = false
|
|
232
|
-
completedList.add(dataMap)
|
|
233
237
|
}
|
|
234
|
-
|
|
238
|
+
dataMap["isPaused"] = false
|
|
239
|
+
completedList.add(dataMap)
|
|
240
|
+
}
|
|
241
|
+
cursor.close()
|
|
235
242
|
|
|
236
|
-
|
|
243
|
+
promise.resolve(gson.toJson(completedList))
|
|
237
244
|
}
|
|
238
245
|
|
|
239
246
|
private fun dateToString(seconds: String): String {
|
|
240
|
-
val secondsLong = seconds.toLong()
|
|
241
|
-
val calendar = Calendar.getInstance()
|
|
242
|
-
calendar.add(Calendar.SECOND, secondsLong.toInt())
|
|
243
|
-
|
|
244
247
|
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
|
245
|
-
return
|
|
248
|
+
return try {
|
|
249
|
+
val secondsLong = seconds.toLong()
|
|
250
|
+
Calendar.getInstance().let {
|
|
251
|
+
it.add(Calendar.SECOND, secondsLong.toInt())
|
|
252
|
+
dateFormat.format(it.time)
|
|
253
|
+
}
|
|
254
|
+
} catch (e: NumberFormatException) {
|
|
255
|
+
// Handle the exception here, for example, return an empty string or throw the exception
|
|
256
|
+
""
|
|
257
|
+
}
|
|
246
258
|
}
|
|
247
259
|
|
|
248
260
|
class AssetParseObserver(activity: Context) : ISegmentedAssetFromParserObserver {
|
|
@@ -250,24 +262,12 @@ class OfflineVideoEngine(private val context: ReactApplicationContext) {
|
|
|
250
262
|
|
|
251
263
|
@SuppressLint("ShowToast")
|
|
252
264
|
override fun complete(asset: ISegmentedAsset?, error: Int, addedToQueue: Boolean) {
|
|
253
|
-
// Show a process when the asset to parsed and added to queue
|
|
254
|
-
// if (asset != null) {
|
|
255
|
-
// Toast.makeText(
|
|
256
|
-
// mActivity,
|
|
257
|
-
// "Asset parsed and " + if (addedToQueue) "added" else "not added" + "to download queue",
|
|
258
|
-
// Toast.LENGTH_LONG
|
|
259
|
-
// ).show()
|
|
260
|
-
// } else {
|
|
261
|
-
// Toast.makeText(mActivity, "Error $error while parsing asset", Toast.LENGTH_LONG).show()
|
|
262
|
-
// }
|
|
263
265
|
}
|
|
264
266
|
}
|
|
265
267
|
|
|
266
|
-
|
|
267
268
|
fun deleteMany(assetIds: ReadableArray, promise: Promise) {
|
|
268
269
|
val assetManager = virtuoso.assetManager
|
|
269
270
|
val result = Arguments.createMap()
|
|
270
|
-
|
|
271
271
|
for (i in 0 until assetIds.size()) {
|
|
272
272
|
val idValue = assetIds.getString(i)
|
|
273
273
|
val asset = assetManager.getByAssetId(idValue)
|
|
@@ -281,20 +281,19 @@ class OfflineVideoEngine(private val context: ReactApplicationContext) {
|
|
|
281
281
|
assetId.remove(idValue)
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
|
-
|
|
285
|
-
promise.resolve(result);
|
|
284
|
+
promise.resolve(result)
|
|
286
285
|
}
|
|
287
286
|
|
|
288
287
|
|
|
289
|
-
|
|
290
|
-
//load asset if it has already been downloaded
|
|
291
|
-
val list: MutableList<IIdentifier
|
|
288
|
+
fun getByAssetId(assetId: String): String? {
|
|
289
|
+
// load asset if it has already been downloaded
|
|
290
|
+
val list: MutableList<IIdentifier> = virtuoso.assetManager.getByAssetId(assetId)
|
|
292
291
|
|
|
293
|
-
list
|
|
292
|
+
list.let {
|
|
294
293
|
if (it.isNotEmpty()) {
|
|
295
294
|
asset = list[0] as VirtuosoSegmentedFile
|
|
296
295
|
|
|
297
|
-
// This a
|
|
296
|
+
// This a workaround to works ancillary files
|
|
298
297
|
val offlineUrl = asset?.playbackURL
|
|
299
298
|
val request = Request.Builder()
|
|
300
299
|
.url(offlineUrl.toString())
|
|
@@ -307,58 +306,121 @@ class OfflineVideoEngine(private val context: ReactApplicationContext) {
|
|
|
307
306
|
keyValueMap["offlineUrl"] = offlineUrl.toString()
|
|
308
307
|
keyValueMap["metadata"] = asset?.metadata.toString()
|
|
309
308
|
|
|
310
|
-
val ancillaryFiles =
|
|
309
|
+
val ancillaryFiles = (asset as ISegmentedAsset).getAncillaryFiles(context)
|
|
311
310
|
|
|
312
|
-
//HERE THE ASSET MANIFEST IS REQUESTED
|
|
311
|
+
// HERE THE ASSET MANIFEST IS REQUESTED
|
|
313
312
|
keyValueMap["ancillary"] = ancillaryFiles
|
|
314
313
|
return gson.toJson(keyValueMap)
|
|
315
314
|
}
|
|
316
315
|
}
|
|
317
316
|
return null
|
|
318
317
|
}
|
|
319
|
-
fun updateUI() {}
|
|
320
318
|
|
|
321
|
-
fun loadBitmovinSourceManager(
|
|
322
|
-
|
|
319
|
+
fun loadBitmovinSourceManager(
|
|
320
|
+
assetId: String,
|
|
321
|
+
nativeId: String,
|
|
322
|
+
startOffset: Double?,
|
|
323
|
+
ancillaries: String,
|
|
324
|
+
promise: Promise
|
|
325
|
+
) {
|
|
326
|
+
virtuoso.assetManager.getByAssetId(assetId)?.firstOrNull()?.let { asset ->
|
|
323
327
|
val sourceManager = BitmovinSourceManager(context, asset as ISegmentedAsset)
|
|
324
328
|
val sourceItem = sourceManager.bitmovinSourceItem
|
|
325
329
|
val playerModule = context.getNativeModule(PlayerModule::class.java)
|
|
326
330
|
if (playerModule != null && sourceItem != null) {
|
|
327
331
|
var player = playerModule.getPlayer(nativeId)
|
|
328
|
-
while(player == null) {
|
|
332
|
+
while (player == null) {
|
|
329
333
|
Thread.sleep(100)
|
|
330
334
|
player = playerModule.getPlayer(nativeId) as Nothing?
|
|
331
335
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
336
|
+
val metadata = JSONObject(asset.metadata)
|
|
337
|
+
val subtitles = JSONArray(metadata["subtitles"] as String)
|
|
338
|
+
val ancillaryFiles = JSONArray(ancillaries)
|
|
339
|
+
for (i in 0 until subtitles.length()) {
|
|
340
|
+
val subtitleMap = Arguments.createMap()
|
|
341
|
+
val subtitle = subtitles.getJSONObject(i)
|
|
342
|
+
|
|
343
|
+
for (j in 0 until ancillaryFiles.length()) {
|
|
344
|
+
val ancillary = ancillaryFiles.getJSONObject(j)
|
|
345
|
+
if (ancillary.getString("description") == subtitle.getString("language")) {
|
|
346
|
+
subtitleMap.putString("url", ancillary.getString("playbackUrl").toString())
|
|
344
347
|
}
|
|
345
|
-
val language: String = subtitle.getString("language")
|
|
346
|
-
val label: String = subtitle.getString("label")
|
|
347
|
-
val format = "vtt"
|
|
348
|
-
sourceItem.addSubtitleTrack(SubtitleTrack(url, language, label, format))
|
|
349
348
|
}
|
|
350
|
-
|
|
351
|
-
|
|
349
|
+
subtitleMap.putString("language", subtitle.getString("language"))
|
|
350
|
+
subtitleMap.putString("label", subtitle.getString("label"))
|
|
351
|
+
subtitleMap.putString("format", "vtt")
|
|
352
|
+
|
|
353
|
+
JsonConverter.toSubtitleTrack(subtitleMap)?.let {
|
|
354
|
+
sourceItem.addSubtitleTrack(it)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (startOffset != null) {
|
|
358
|
+
sourceItem.options.startOffset = startOffset
|
|
359
|
+
}
|
|
360
|
+
val metaDataMap = mutableMapOf<String, String>()
|
|
361
|
+
|
|
362
|
+
val data = metadata.getJSONObject("data")
|
|
363
|
+
val infoVideoPlayer = data.getJSONObject("infoVideoPlayer")
|
|
364
|
+
|
|
365
|
+
infoVideoPlayer.optString("title").let { title ->
|
|
366
|
+
if (title.isNotBlank()) {
|
|
367
|
+
sourceItem.title = title
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
infoVideoPlayer.optString("description").let { description ->
|
|
372
|
+
if (description.isNotBlank()) {
|
|
373
|
+
metaDataMap["description"] = description
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
infoVideoPlayer.optString("advisoryClassification").let { advisoryClassification ->
|
|
378
|
+
if (advisoryClassification.isNotBlank()) {
|
|
379
|
+
metaDataMap["advisoryClassification"] = advisoryClassification
|
|
352
380
|
}
|
|
353
|
-
player.load(sourceItem)
|
|
354
|
-
promise.resolve(true)
|
|
355
381
|
}
|
|
382
|
+
|
|
383
|
+
infoVideoPlayer.optString("advisoryDescription").let { advisoryDescription ->
|
|
384
|
+
if (advisoryDescription.isNotBlank()) {
|
|
385
|
+
metaDataMap["advisoryDescription"] = advisoryDescription
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
sourceItem.metadata = metaDataMap
|
|
390
|
+
player.load(sourceItem)
|
|
391
|
+
promise.resolve(true)
|
|
356
392
|
}
|
|
357
393
|
}
|
|
358
394
|
promise.reject("Error", "Error loading asset")
|
|
359
395
|
}
|
|
360
396
|
|
|
361
|
-
|
|
362
|
-
|
|
397
|
+
fun getAuthenticationStatus(promise: Promise) {
|
|
398
|
+
promise.resolve(virtuoso.backplane.authenticationStatus)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
fun configParameters(params: String, promise: Promise){
|
|
402
|
+
try {
|
|
403
|
+
val data = JSONObject(params)
|
|
363
404
|
|
|
405
|
+
if (data.has("minimumLowBandWidth"))
|
|
406
|
+
data.getDouble("minimumLowBandWidth").let {
|
|
407
|
+
minimumLowBandWidth = it / 1000
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
if (data.has("maxStorageAllowed"))
|
|
412
|
+
data.getLong("maxStorageAllowed").let {
|
|
413
|
+
virtuoso.settings.maxStorageAllowed = it / 1000
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (data.has("headroom"))
|
|
417
|
+
data.getLong("headroom").let {
|
|
418
|
+
virtuoso.settings.headroom = it / 1000
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
promise.resolve("Penthera configuration successfully")
|
|
422
|
+
} catch (e: Exception) {
|
|
423
|
+
promise.reject(e)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
364
426
|
}
|
|
@@ -6,27 +6,9 @@ data class Item(
|
|
|
6
6
|
|
|
7
7
|
var id: String,
|
|
8
8
|
|
|
9
|
-
@SerializedName("asset_id")
|
|
10
|
-
val assetId: String = "",
|
|
11
|
-
|
|
12
9
|
@SerializedName("title")
|
|
13
10
|
val title: String = "",
|
|
14
11
|
|
|
15
|
-
@SerializedName("content_url")
|
|
16
|
-
val contentUrl: String = "",
|
|
17
|
-
|
|
18
|
-
@SerializedName("poster")
|
|
19
|
-
val poster: String = "",
|
|
20
|
-
|
|
21
|
-
@SerializedName("thumbnail")
|
|
22
|
-
val thumbnail: String = "",
|
|
23
|
-
|
|
24
|
-
@SerializedName("en_subtitle")
|
|
25
|
-
val subtitle: String? = "",
|
|
26
|
-
|
|
27
|
-
@SerializedName("drm")
|
|
28
|
-
var drm: String? = null,
|
|
29
|
-
|
|
30
12
|
)
|
|
31
13
|
|
|
32
14
|
|
|
@@ -11,10 +11,12 @@ import android.content.pm.PackageManager
|
|
|
11
11
|
import android.os.Build
|
|
12
12
|
import android.util.Log
|
|
13
13
|
import androidx.core.app.NotificationCompat
|
|
14
|
+
import androidx.core.content.ContextCompat
|
|
14
15
|
import com.google.gson.Gson
|
|
15
16
|
import com.penthera.virtuososdk.Common
|
|
16
17
|
import com.penthera.virtuososdk.client.IAsset
|
|
17
18
|
import com.penthera.virtuososdk.client.IEvent
|
|
19
|
+
import com.penthera.virtuososdk.utility.CommonUtil.getApplicationContext
|
|
18
20
|
import com.takeoffmediareactnativepenthera.PentheraModule
|
|
19
21
|
import com.takeoffmediareactnativepenthera.R
|
|
20
22
|
import com.takeoffmediareactnativepenthera.virtuoso.data.Item
|
|
@@ -22,9 +24,9 @@ import com.takeoffmediareactnativepenthera.virtuoso.data.Item
|
|
|
22
24
|
class NotificationFactory(private val applicationName: String) {
|
|
23
25
|
|
|
24
26
|
companion object {
|
|
25
|
-
fun channelId() = "
|
|
26
|
-
fun channelName() = "
|
|
27
|
-
fun channelDescription() = "
|
|
27
|
+
fun channelId() = "Britbox"
|
|
28
|
+
fun channelName() = "Britbox"
|
|
29
|
+
fun channelDescription() = "Downloads"
|
|
28
30
|
|
|
29
31
|
private val TAG = NotificationFactory::class.java.simpleName
|
|
30
32
|
private var notificationChannel : NotificationChannel? = null
|
|
@@ -108,7 +110,7 @@ class NotificationFactory(private val applicationName: String) {
|
|
|
108
110
|
|
|
109
111
|
Common.Notifications.INTENT_NOTIFICATION_DOWNLOAD_COMPLETE -> {
|
|
110
112
|
if (file != null) {
|
|
111
|
-
Log.d(TAG, "DOWNLOAD COMPLETE NOTIFICATION FOR " + file
|
|
113
|
+
Log.d(TAG, "DOWNLOAD COMPLETE NOTIFICATION FOR " + file.uuid + " stat: " + if (hasInfo) info else "unknown")
|
|
112
114
|
} else {
|
|
113
115
|
Log.d(TAG, "DOWNLOAD COMPLETE NOTIFICATION FOR UNKNOWN" + " stat: " + if (hasInfo) info else "unknown")
|
|
114
116
|
}
|
|
@@ -116,7 +118,7 @@ class NotificationFactory(private val applicationName: String) {
|
|
|
116
118
|
}
|
|
117
119
|
Common.Notifications.INTENT_NOTIFICATION_DOWNLOAD_START ->{
|
|
118
120
|
if(file != null) {
|
|
119
|
-
Log.d(TAG, "DOWNLOAD START NOTIFICATION FOR " + file
|
|
121
|
+
Log.d(TAG, "DOWNLOAD START NOTIFICATION FOR " + file.uuid + " stat: " + if (hasInfo) info else "unknown")
|
|
120
122
|
} else {
|
|
121
123
|
Log.d(TAG, "DOWNLOAD START NOTIFICATION FOR UNKNOWN" + " stat: " + if (hasInfo) info else "unknown")
|
|
122
124
|
}
|
|
@@ -143,7 +145,7 @@ class NotificationFactory(private val applicationName: String) {
|
|
|
143
145
|
|
|
144
146
|
Common.Notifications.INTENT_NOTIFICATION_DOWNLOAD_UPDATE -> {
|
|
145
147
|
if (file != null) {
|
|
146
|
-
Log.d(TAG, "DOWNLOAD UPDATE NOTIFICATION FOR " + file
|
|
148
|
+
Log.d(TAG, "DOWNLOAD UPDATE NOTIFICATION FOR " + file.uuid + " stat: " + if (hasInfo) info else "unknown")
|
|
147
149
|
} else {
|
|
148
150
|
Log.d(TAG, "DOWNLOAD UPDATE NOTIFICATION FOR UNKNOWN" + " stat: " + if (hasInfo) info else "unknown")
|
|
149
151
|
}
|
|
@@ -178,7 +180,7 @@ class NotificationFactory(private val applicationName: String) {
|
|
|
178
180
|
* @param asset the asset (may be null)
|
|
179
181
|
* @return the notification.
|
|
180
182
|
*/
|
|
181
|
-
private fun
|
|
183
|
+
private fun createNotification(type: Int, context: Context, asset: IAsset?): Notification {
|
|
182
184
|
var title = "$applicationName: "
|
|
183
185
|
var contentText = ""
|
|
184
186
|
var progress = -1
|
|
@@ -236,7 +238,8 @@ class NotificationFactory(private val applicationName: String) {
|
|
|
236
238
|
setSmallIcon(R.drawable.small_logo)
|
|
237
239
|
setContentTitle(title)
|
|
238
240
|
setContentIntent(pendingIntent)
|
|
239
|
-
color
|
|
241
|
+
// The color of notification. This requires Android 21 or higher.
|
|
242
|
+
color = ContextCompat.getColor(getApplicationContext(), R.color.primary)
|
|
240
243
|
setContentText(contentText)
|
|
241
244
|
if(progress >= 0)setProgress(100, progress, false)
|
|
242
245
|
setWhen(System.currentTimeMillis())
|