@24i/smartapps-bigscreen-rnv-build-engine 0.17.6-alpha.15 → 0.17.6-alpha.16

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.
Files changed (30) hide show
  1. package/dist/src/resolvers/resolveBaseUrl.js +3 -1
  2. package/dist/src/sdks/sdk-androidtv/sdkAndroidtv.js +22 -8
  3. package/dist/templates/platforms/androidtv/project/amazoniap/build.gradle +2 -2
  4. package/dist/templates/platforms/androidtv/project/app/build.gradle +17 -21
  5. package/dist/templates/platforms/androidtv/project/app/proguard-rules.pro +15 -0
  6. package/dist/templates/platforms/androidtv/project/app/src/bigscreenAppstage/res/raw/configuration.json +1 -2
  7. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeFromJavaScript.kt +4 -58
  8. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeToJavaScript.kt +15 -0
  9. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/configuration/BridgeConfig.kt +2 -1
  10. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ActivityModule.kt +0 -3
  11. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ApplicationModule.kt +2 -2
  12. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/PerActivity.kt +0 -0
  13. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryConfigured.kt +33 -0
  14. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryExoPlayerCustomized.kt +7 -1
  15. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryTheoPlayerCustomized.kt +14 -0
  16. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryVersion.kt +27 -0
  17. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/SourceDrmOverridden.kt +42 -0
  18. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/model/MediaEventType.kt +3 -0
  19. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/SourceParser.kt +89 -0
  20. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/Mainview.kt +0 -3
  21. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/PlayerCache.kt +2 -2
  22. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/WebViewActivity.kt +24 -83
  23. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/viewmodel/WebViewModel.kt +48 -111
  24. package/dist/templates/platforms/androidtv/project/app/src/main/res/layout/activity_web_view.xml +23 -71
  25. package/dist/templates/platforms/androidtv/project/common/build.gradle +2 -2
  26. package/dist/templates/platforms/androidtv/project/googleiap/build.gradle +2 -2
  27. package/package.json +1 -1
  28. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/jump/JumpAnalytics.kt +0 -211
  29. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/ContentModelParser.kt +0 -16
  30. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/DeviceInfoParser.kt +0 -22
@@ -8,7 +8,9 @@ const resolveBaseUrl = ({ platform, scheme, flavour }) => {
8
8
  c.platform = platform;
9
9
  c.runtime.scheme = scheme;
10
10
  c.runtime.appId = flavour;
11
- const hostedBaseUrl = c.buildConfig?.common.hostedUrl.baseUrl;
11
+ const hostedBaseUrl = c.buildConfig?.common?.hostedUrl?.baseUrl;
12
+ if (!hostedBaseUrl)
13
+ return '';
12
14
  const fullBaseUrl = `${hostedBaseUrl}/builds/${platform}/${flavour}`;
13
15
  return (0, constructFullUrl_1.constructFullUrl)({ baseUrl: fullBaseUrl, scheme, c });
14
16
  };
@@ -22,11 +22,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
29
  exports.handleAndroidTVSdk = exports.configureAndroidTVProject = exports.buildAndroidTVProject = void 0;
27
30
  const fs = __importStar(require("fs"));
28
31
  const path = __importStar(require("path"));
29
32
  const os = __importStar(require("os"));
33
+ const ip_1 = __importDefault(require("ip"));
30
34
  const semver = __importStar(require("semver"));
31
35
  const child_process_1 = require("child_process");
32
36
  const rnv_1 = require("rnv");
@@ -139,8 +143,8 @@ const configureProject = (c) => {
139
143
  const versionCode = parseInt(`${major}${minor}${patch}00`, 10);
140
144
  const appId = rnv_1.Common.getConfigProp(c, c.platform, 'id', '');
141
145
  const minSdkVersion = rnv_1.Common.getConfigProp(c, c.platform, 'minSdkVersion', 21);
142
- const targetSdkVersion = rnv_1.Common.getConfigProp(c, c.platform, 'targetSdkVersion', 31);
143
- const compileSdkVersion = rnv_1.Common.getConfigProp(c, c.platform, 'compileSdkVersion', 31);
146
+ const targetSdkVersion = rnv_1.Common.getConfigProp(c, c.platform, 'targetSdkVersion', 33);
147
+ const compileSdkVersion = rnv_1.Common.getConfigProp(c, c.platform, 'compileSdkVersion', 33);
144
148
  const injects = [{
145
149
  pattern: '{{MIN_SDK_VERSION}}',
146
150
  override: minSdkVersion,
@@ -164,9 +168,9 @@ const configureProject = (c) => {
164
168
  rnv_1.FileUtils.writeCleanFile(buildGradleFilePath, buildGradleFilePath, injects, null, c);
165
169
  };
166
170
  const getHostedAppEntryUrl = (c) => {
167
- const { platform, runtime } = c;
171
+ const { platform, runtime, program } = c;
168
172
  let baseUrl = '';
169
- if (c.program.productionPackagesHostedUrl) {
173
+ if (program.productionPackagesHostedUrl) {
170
174
  baseUrl = (0, resolvers_1.resolveProductionPackagesBaseUrl)(c);
171
175
  }
172
176
  else {
@@ -176,18 +180,28 @@ const getHostedAppEntryUrl = (c) => {
176
180
  flavour: runtime.appId,
177
181
  });
178
182
  }
179
- return `${baseUrl}/public/index.html`;
183
+ if (baseUrl)
184
+ return `${baseUrl}/public/index.html`;
185
+ const localIp = program.debugIp ?? ip_1.default.address();
186
+ const localPort = runtime.port ?? 8100;
187
+ return `http://${localIp}:${localPort}/`;
180
188
  };
181
189
  const configureEntryUrl = (c) => {
182
190
  rnv_1.Logger.logTask('configureEntryUrl');
191
+ const buildGradleFileName = 'build.gradle';
192
+ const buildGradleFilePath = path.join(rnv_1.Common.getPlatformProjectDir(c), 'app', buildGradleFileName);
183
193
  const entryUrl = getHostedAppEntryUrl(c);
184
- const configFileName = 'configuration.json';
194
+ const theoLicense = process.env['THEO_LICENSE'] ??
195
+ rnv_1.Common.getConfigProp(c, c.platform, 'theoLicense', '');
185
196
  const injects = [{
186
197
  pattern: '{{APP_URL}}',
187
198
  override: entryUrl,
199
+ }, {
200
+ pattern: '{{THEO_LICENSE}}',
201
+ override: theoLicense,
188
202
  }];
189
- const file = path.join(rnv_1.Common.getPlatformProjectDir(c), 'app/src', flavourName, 'res/raw', configFileName);
190
- rnv_1.FileUtils.writeCleanFile(file, file, injects, null, c);
203
+ rnv_1.Common.addSystemInjects(c, injects);
204
+ rnv_1.FileUtils.writeCleanFile(buildGradleFilePath, buildGradleFilePath, injects, null, c);
191
205
  };
192
206
  const configureAndroidTVProject = async (c) => {
193
207
  rnv_1.Logger.logTask('configureAndroidTVProject');
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-android'
3
3
 
4
4
  android {
5
- compileSdkVersion 31
5
+ compileSdkVersion 33
6
6
 
7
7
  compileOptions {
8
8
  sourceCompatibility JavaVersion.VERSION_1_8
@@ -11,7 +11,7 @@ android {
11
11
 
12
12
  defaultConfig {
13
13
  minSdkVersion 21
14
- targetSdkVersion 30
14
+ targetSdkVersion 33
15
15
 
16
16
  versionCode 1
17
17
  versionName "1.0"
@@ -1,8 +1,9 @@
1
1
  apply plugin: 'com.android.application'
2
2
  apply plugin: 'kotlin-android'
3
3
  apply plugin: 'kotlin-kapt'
4
- apply plugin: 'com.google.gms.google-services'
5
- apply plugin: 'com.google.firebase.crashlytics'
4
+
5
+ def theoLicense = '{{THEO_LICENSE}}'
6
+ def useTheoPlayer = theoLicense != ''
6
7
 
7
8
  android {
8
9
  compileSdkVersion {{COMPILE_SDK_VERSION}}
@@ -32,6 +33,10 @@ android {
32
33
 
33
34
  // necessary for Fire OS - installation of debug build fails otherwise
34
35
  multiDexEnabled true
36
+
37
+ buildConfigField "String", "APP_URL", '"{{APP_URL}}"'
38
+ buildConfigField "String", "THEO_LICENSE", "\"$theoLicense\""
39
+ buildConfigField "Boolean", "startWithHighVideoQuality", "true"
35
40
  }
36
41
 
37
42
  signingConfigs {
@@ -40,8 +45,6 @@ android {
40
45
  keyPassword '{{KEY_PASSWORD}}'
41
46
  storeFile file('{{STORE_FILE}}')
42
47
  storePassword '{{STORE_PASSWORD}}'
43
- v1SigningEnabled true
44
- v2SigningEnabled true
45
48
  }
46
49
  }
47
50
 
@@ -57,7 +60,8 @@ android {
57
60
  }
58
61
 
59
62
  buildFeatures {
60
- dataBinding true
63
+ buildConfig true
64
+ viewBinding true
61
65
  }
62
66
 
63
67
  flavorDimensions "bridge"
@@ -74,16 +78,6 @@ android {
74
78
  }
75
79
  }
76
80
 
77
- //Enable GoogleServices and Crashlytics for specified variant
78
- android.applicationVariants.all { variant ->
79
- project.tasks.getByName('process' + variant.name.capitalize() + 'GoogleServices').enabled = false
80
- tasks.whenTaskAdded { task ->
81
- if (task.name.toLowerCase().contains("crashlytics")) {
82
- task.enabled = false
83
- }
84
- }
85
- }
86
-
87
81
  dependencies {
88
82
  implementation fileTree(include: ['*.jar'], dir: 'libs')
89
83
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
@@ -93,9 +87,6 @@ dependencies {
93
87
  compileOnly "javax.annotation:jsr250-api:1.0"
94
88
  implementation "androidx.appcompat:appcompat:1.4.2"
95
89
  implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
96
- implementation "androidx.recyclerview:recyclerview:1.2.1"
97
- implementation 'com.google.firebase:firebase-crashlytics:18.2.11'
98
- implementation 'com.google.firebase:firebase-analytics:21.0.0'
99
90
 
100
91
  implementation "com.google.dagger:dagger:2.42"
101
92
  kapt "com.google.dagger:dagger-compiler:2.42"
@@ -104,9 +95,14 @@ dependencies {
104
95
  implementation "com.squareup.retrofit2:converter-gson:2.5.0"
105
96
  implementation "com.squareup.okhttp3:logging-interceptor:4.9.2"
106
97
  implementation "com.squareup.okhttp3:okhttp:4.9.2"
107
- implementation "com.twentyfouri.player:exoplayer:0.6.0-alpha.23"
108
- implementation 'com.google.android.exoplayer:extension-okhttp:2.17.1'
109
- implementation "com.jumptvs.jumpkit:jumpkit-exoplayer:2.6.5"
98
+ if (useTheoPlayer) {
99
+ compileOnly "com.twentyfouri.player:exoplayer:0.6.0-alpha.36"
100
+ implementation "com.twentyfouri.player:theoplayer:0.6.0-alpha.36"
101
+ } else {
102
+ implementation "com.twentyfouri.player:exoplayer:0.6.0-alpha.36"
103
+ compileOnly "com.twentyfouri.player:theoplayer:0.6.0-alpha.36"
104
+ }
110
105
 
111
106
  implementation project(':common')
112
107
  }
108
+
@@ -29,4 +29,19 @@
29
29
  -keep class com.amazon.** {*;}
30
30
  -keepattributes *Annotation*
31
31
 
32
+ -keep class com.theoplayer.android.** {*;}
33
+ -dontwarn com.theoplayer.android.**
34
+ -keep public class com.google.android.gms.* { public *; }
35
+ -dontwarn com.google.android.gms.**
36
+
37
+ # In case of using yospace integration
38
+ -keep class com.yospace.util.** {*;}
39
+ -dontwarn com.yospace.util.**
40
+
41
+ # For native Google IMA integration
42
+ -keep class com.google.obf.** { *; }
43
+ -keep interface com.google.obf.** { *; }
44
+ -keep class com.google.ads.interactivemedia.** { *; }
45
+ -keep interface com.google.ads.interactivemedia.** { *; }
46
+
32
47
  -optimizationpasses 1
@@ -1,9 +1,8 @@
1
1
  {
2
- "baseUrl": "{{APP_URL}}",
3
2
  "customizableUrl": false,
4
3
  "mediaEventPrefix": "player:",
5
4
  "startWithHighVideoQuality": true,
6
5
  "drm": {
7
- "overrideDrmCallback": true
6
+ "overrideDrmCallback": false
8
7
  }
9
8
  }
@@ -8,8 +8,9 @@ import android.webkit.JavascriptInterface
8
8
  import com.google.gson.JsonObject
9
9
  import com.twentyfouri.player.base.TextTrack
10
10
  import com.twentyfouri.player.base.TrackKind
11
- import com.twentyfouri.tvbridge.webview.parser.ContentModelParser.stringToJson
11
+ import com.twentyfouri.tvbridge.webview.parser.SourceParser.stringToJson
12
12
  import com.twentyfouri.tvbridge.webview.parser.PlaybackInfoParser.parse
13
+ import com.twentyfouri.tvbridge.webview.parser.SourceParser
13
14
  import com.twentyfouri.tvbridge.webview.parser.TrackJsonModelParser.audioFromJson
14
15
  import com.twentyfouri.tvbridge.webview.parser.TrackJsonModelParser.textFromJson
15
16
  import com.twentyfouri.tvbridge.webview.parser.TrackJsonModelParser.toJson
@@ -69,19 +70,8 @@ class BridgeFromJavaScript(
69
70
  Log.d(LOG_TAG, "bridgeJavaScriptToAndroid_SetVideoPath = $jsonString")
70
71
  try {
71
72
  viewModel.stopPlayer()
72
- val contentModel = stringToJson(jsonString)
73
- contentModel?.streamType = mimeType?.let {
74
- when {
75
- mimeType.contains("application/dash+xml") -> "mpd"
76
- mimeType.contains("application/vnd.apple.mpegurl") -> "m3u8"
77
- mimeType.contains("video/mp4") -> "mp4"
78
- mimeType.contains("application/vnd.ms-sstr+xml") -> "ism"
79
- mimeType.contains("audio/mpeg") -> "mp3"
80
- else -> null
81
- }
82
- }
83
- if (contentModel?.streamUrl != null) {
84
- viewModel.setVideo(contentModel)
73
+ stringToJson(jsonString)?.also { source ->
74
+ viewModel.setVideo(source)
85
75
  }
86
76
  } catch (e: Exception) {
87
77
  Log.v(LOG_TAG, "bridgeJavaScriptToAndroid_SetVideoPathError - ${e.message}")
@@ -282,50 +272,6 @@ class BridgeFromJavaScript(
282
272
  viewModel.subtitleTrack?.let { toJson(it) } ?: DISABLED_SUBTITLE_TRACK
283
273
  }
284
274
 
285
- /*
286
- Returns VIDEO track BITRATE, if not available returns null
287
- */
288
- @JavascriptInterface
289
- fun bridgeJavaScriptToAndroid_GetBitrate(): Int? = runBlocking("bridgeJavaScriptToAndroid_GetBitrate") {
290
- viewModel.videoTrack?.bitrate
291
- }
292
-
293
- /*
294
- Returns VIDEO track RENDITION, if not available returns null
295
- */
296
- @JavascriptInterface
297
- fun bridgeJavaScriptToAndroid_GetRendition(): String? = runBlocking("bridgeJavaScriptToAndroid_GetRendition") {
298
- viewModel.videoTrack?.run {
299
- return@runBlocking "${width}x${height}${formatBitrate(bitrate)}"
300
- }
301
- null
302
- }
303
-
304
- private fun formatBitrate(bitrate: Int): String {
305
- return when {
306
- bitrate <= 0 -> ""
307
- bitrate < 1e3 -> "@${bitrate}bps"
308
- bitrate < 1e6 -> "@${(bitrate / 1e3).roundToInt()}Kbps"
309
- else -> "@${(bitrate / 1e4).roundToInt() / 1e2}Mbps"
310
- }
311
- }
312
-
313
- /*
314
- Returns AUDIO track CODEC, if not available returns null
315
- */
316
- @JavascriptInterface
317
- fun bridgeJavaScriptToAndroid_GetAudioCodec(): String? = runBlocking("bridgeJavaScriptToAndroid_GetAudioCodec") {
318
- viewModel.audioTrack?.codec
319
- }
320
-
321
- /*
322
- Returns VIDEO track CODEC, if not available returns null
323
- */
324
- @JavascriptInterface
325
- fun bridgeJavaScriptToAndroid_GetVideoCodec(): String? = runBlocking("bridgeJavaScriptToAndroid_GetVideoCodec") {
326
- viewModel.videoTrack?.codec
327
- }
328
-
329
275
  /*
330
276
  Set the cookies to localstorage
331
277
  */
@@ -2,10 +2,13 @@ package com.twentyfouri.tvbridge.bridge
2
2
 
3
3
  import android.util.Log
4
4
  import com.twentyfouri.player.base.AudioTrack
5
+ import com.twentyfouri.player.base.DefaultSourceSerializer
5
6
  import com.twentyfouri.player.base.TextTrack
7
+ import com.twentyfouri.player.base.TimelineEvent
6
8
  import com.twentyfouri.tvbridge.bridge.BridgeFromJavaScript.Companion.LOG_TAG
7
9
  import com.twentyfouri.tvbridge.configuration.BridgeConfig
8
10
  import com.twentyfouri.tvbridge.webview.parser.TrackJsonModelParser.toJson
11
+ import org.json.JSONArray
9
12
 
10
13
  class BridgeToJavaScript(
11
14
  config: BridgeConfig,
@@ -60,6 +63,18 @@ class BridgeToJavaScript(
60
63
  executeJavaScript(mediaEventString)
61
64
  }
62
65
 
66
+ fun bridgeAndroidToJavaScript_MediaAdBreaksEvent(
67
+ mediaEvent: String,
68
+ timeline: List<TimelineEvent>
69
+ ) {
70
+ val serializer = DefaultSourceSerializer()
71
+ val adsJson = JSONArray(timeline.map { serializer.toPersistentMap(it) }).toString()
72
+
73
+ val mediaEventString = "javascript:((function dispatchEvent(){var evt = document.createEvent('Events');evt.initEvent('$mediaEventPrefix$mediaEvent',true,true);evt.ads='$adsJson';document.dispatchEvent(evt);})())"
74
+ Log.v(LOG_TAG, mediaEventString)
75
+ executeJavaScript(mediaEventString)
76
+ }
77
+
63
78
  fun bridgeAndroidToJavaScript_IAPValidationError(message: String) {
64
79
  Log.d(LOG_TAG, "bridgeAndroidToJavaScript_IAPValidationError")
65
80
  executeJavaScript("javascript:((function dispatchEvent(){var evt = document.createEvent('Events');evt.initEvent('${iapEventPrefix}iapError',true,true);evt.message='$message';document.dispatchEvent(evt);})())")
@@ -3,7 +3,7 @@ package com.twentyfouri.tvbridge.configuration
3
3
  import com.twentyfouri.tvbridge.BuildConfig
4
4
 
5
5
  class BridgeConfig {
6
- var baseUrl: String = "http://portal.24imedia.tv/"
6
+ var baseUrl: String = BuildConfig.APP_URL
7
7
  var userAgent: UserAgent = UserAgent()
8
8
  var drm: Drm = Drm()
9
9
  var isEnabledTouchSound: Boolean = false
@@ -13,4 +13,5 @@ class BridgeConfig {
13
13
  var iapEventPrefix: String = ""
14
14
  var customizableUrl: Boolean = BuildConfig.DEBUG
15
15
  var startWithHighVideoQuality: Boolean = false
16
+ var theoLicense: String = BuildConfig.THEO_LICENSE
16
17
  }
@@ -1,9 +1,6 @@
1
1
  package com.twentyfouri.tvbridge.global.di
2
2
 
3
3
  import android.app.Activity
4
- import com.twentyfouri.player.base.PlayerFactoryBase
5
- import com.twentyfouri.tvbridge.configuration.BridgeConfig
6
- import com.twentyfouri.tvbridge.global.utils.PlayerFactoryExoPlayerCustomized
7
4
  import dagger.Module
8
5
  import dagger.Provides
9
6
 
@@ -7,7 +7,7 @@ import com.twentyfouri.tvbridge.common.NullIapService
7
7
  import com.twentyfouri.tvbridge.configuration.BridgeConfig
8
8
  import com.twentyfouri.tvbridge.global.BaseApplication
9
9
  import com.twentyfouri.tvbridge.global.utils.LocalStorage
10
- import com.twentyfouri.tvbridge.global.utils.PlayerFactoryExoPlayerCustomized
10
+ import com.twentyfouri.tvbridge.global.utils.PlayerFactoryConfigured
11
11
  import com.twentyfouri.tvbridge.sound.TouchPlayer
12
12
  import dagger.Module
13
13
  import dagger.Provides
@@ -46,6 +46,6 @@ class ApplicationModule(
46
46
  @Provides
47
47
  @Singleton
48
48
  fun providePlayerFactory(config: BridgeConfig): PlayerFactoryBase =
49
- PlayerFactoryExoPlayerCustomized(config)
49
+ PlayerFactoryConfigured.buildFactory(config)
50
50
 
51
51
  }
@@ -0,0 +1,33 @@
1
+ package com.twentyfouri.tvbridge.global.utils
2
+
3
+ import com.twentyfouri.player.base.*
4
+ import com.twentyfouri.player.theoplayer.PlayerFactoryTheoPlayer
5
+ import com.twentyfouri.tvbridge.configuration.BridgeConfig
6
+
7
+ object PlayerFactoryConfigured {
8
+
9
+ fun buildFactory(bridgeConfig: BridgeConfig): PlayerFactoryBase {
10
+ var factory: PlayerFactoryBase? = null
11
+ if (bridgeConfig.theoLicense.isNotEmpty()) {
12
+ factory = factory ?: buildTheoFactory(bridgeConfig)
13
+ }
14
+ factory = factory ?: buildExoFactory(bridgeConfig)
15
+ return factory ?: throw Exception("Cannot create player factory")
16
+ }
17
+
18
+ private fun buildExoFactory(bridgeConfig: BridgeConfig): PlayerFactoryBase? {
19
+ try {
20
+ return PlayerFactoryExoPlayerCustomized(bridgeConfig)
21
+ } catch (e: NoClassDefFoundError) {
22
+ return null
23
+ }
24
+ }
25
+
26
+ private fun buildTheoFactory(bridgeConfig: BridgeConfig): PlayerFactoryBase? {
27
+ try {
28
+ return PlayerFactoryTheoPlayerCustomized(bridgeConfig)
29
+ } catch (e: NoClassDefFoundError) {
30
+ return null
31
+ }
32
+ }
33
+ }
@@ -2,6 +2,7 @@ package com.twentyfouri.tvbridge.global.utils
2
2
 
3
3
  import android.content.Context
4
4
  import com.google.android.exoplayer2.C
5
+ import com.google.android.exoplayer2.ExoPlayerLibraryInfo
5
6
  import com.google.android.exoplayer2.drm.DefaultDrmSessionManager
6
7
  import com.google.android.exoplayer2.drm.DrmSessionManager
7
8
  import com.google.android.exoplayer2.drm.FrameworkMediaDrm
@@ -17,7 +18,12 @@ import com.twentyfouri.tvbridge.configuration.BridgeConfig
17
18
 
18
19
  class PlayerFactoryExoPlayerCustomized(
19
20
  private val config: BridgeConfig
20
- ) : PlayerFactoryExoPlayer() {
21
+ ) : PlayerFactoryExoPlayer(), PlayerFactoryVersion {
22
+
23
+ override val engineName: String = "Exoplayer"
24
+
25
+ override val engineVersion: String = ExoPlayerLibraryInfo.VERSION
26
+
21
27
  override fun createSharedComponents(context: Context): SharedComponents =
22
28
  CustomizedSharedComponents(context)
23
29
 
@@ -0,0 +1,14 @@
1
+ package com.twentyfouri.tvbridge.global.utils
2
+
3
+ import com.theoplayer.android.api.THEOplayerGlobal
4
+ import com.twentyfouri.player.theoplayer.PlayerFactoryTheoPlayer
5
+ import com.twentyfouri.tvbridge.configuration.BridgeConfig
6
+
7
+ class PlayerFactoryTheoPlayerCustomized(
8
+ private val config: BridgeConfig
9
+ ) : PlayerFactoryTheoPlayer(config.theoLicense), PlayerFactoryVersion {
10
+
11
+ override val engineName: String = "THEOPlayer"
12
+
13
+ override val engineVersion: String = THEOplayerGlobal.getVersion()
14
+ }
@@ -0,0 +1,27 @@
1
+ package com.twentyfouri.tvbridge.global.utils
2
+
3
+ import com.twentyfouri.player.base.PlayerFactoryBase
4
+
5
+ interface PlayerFactoryVersion {
6
+ val engineName: String
7
+ val engineVersion: String
8
+
9
+ private data class Fixed(
10
+ override val engineName: String,
11
+ override val engineVersion: String
12
+ ): PlayerFactoryVersion
13
+
14
+ companion object {
15
+ fun from(factory: PlayerFactoryBase): PlayerFactoryVersion {
16
+ (factory as? PlayerFactoryVersion)?.also { return it }
17
+
18
+ // fallback to just engine name
19
+ val engineName = factory.javaClass.simpleName
20
+ .replace("PlayerFactory", "")
21
+ .replace("Customized", "")
22
+ .lowercase()
23
+ val engineVersion = "0.0.0"
24
+ return Fixed(engineName, engineVersion)
25
+ }
26
+ }
27
+ }
@@ -1,7 +1,11 @@
1
1
  package com.twentyfouri.tvbridge.global.utils
2
2
 
3
+ import com.twentyfouri.player.base.Source
3
4
  import com.twentyfouri.player.base.SourceAuthorization
4
5
  import com.twentyfouri.player.base.SourceDrm
6
+ import com.twentyfouri.player.base.SourceDrmPlayready
7
+ import com.twentyfouri.player.base.SourceDrmWidevine
8
+ import com.twentyfouri.player.base.buildUpon
5
9
  import java.net.URI
6
10
 
7
11
  open class SourceDrmOverridden protected constructor(
@@ -33,6 +37,17 @@ open class SourceDrmOverridden protected constructor(
33
37
  var forceLicenseServer: Boolean = false
34
38
  var authorization: SourceAuthorization? = null
35
39
 
40
+ open fun applyFrom(source: SourceDrm) {
41
+ when (source) {
42
+ is SourceDrmOverridden -> applyFrom(source)
43
+ is SourceDrmWidevine -> applyFrom(source)
44
+ is SourceDrmPlayready -> applyFrom(source)
45
+ else -> {
46
+ packageName = source.packageName
47
+ }
48
+ }
49
+ }
50
+
36
51
  open fun applyFrom(source: SourceDrmOverridden) {
37
52
  packageName = source.packageName
38
53
  licenseServer = source.licenseServer
@@ -40,9 +55,36 @@ open class SourceDrmOverridden protected constructor(
40
55
  authorization = source.authorization
41
56
  }
42
57
 
58
+ open fun applyFrom(source: SourceDrmWidevine) {
59
+ packageName = source.packageName
60
+ licenseServer = source.licenseServer
61
+ forceLicenseServer = source.forceLicenseServer
62
+ authorization = source.authorization
63
+ }
64
+
65
+ open fun applyFrom(source: SourceDrmPlayready) {
66
+ packageName = source.packageName
67
+ licenseServer = source.licenseServer
68
+ forceLicenseServer = source.forceLicenseServer
69
+ authorization = source.authorization
70
+ }
71
+
43
72
  override fun build() =
44
73
  SourceDrmOverridden(this)
45
74
  }
75
+
76
+ companion object {
77
+ fun replaceSource(source: Source): Source {
78
+ if (source.drm.isEmpty()) return source
79
+ return source.buildUpon {
80
+ drm = drm.mapTo(mutableListOf()) { sourceDrm ->
81
+ SourceDrmOverridden {
82
+ applyFrom(sourceDrm)
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
46
88
  }
47
89
 
48
90
  inline fun SourceDrmOverridden(block: SourceDrmOverridden.Builder.() -> Unit) =
@@ -19,4 +19,7 @@ object MediaEventType {
19
19
  const val KEY_UP = "keyup"
20
20
  const val KEY_DOWN = "keydown"
21
21
  const val TRACKS_CHANGED = "tracksChanged"
22
+ const val AD_BREAK_START = "adbreakstart"
23
+ const val AD_BREAK_END = "adbreakend"
24
+ const val AD_BREAKS_RESCHEDULED = "adbreaksrescheduled"
22
25
  }
@@ -0,0 +1,89 @@
1
+ package com.twentyfouri.tvbridge.webview.parser
2
+
3
+ import com.twentyfouri.player.base.*
4
+ import com.twentyfouri.tvbridge.global.utils.SourceDrmOverridden
5
+ import org.json.JSONException
6
+ import org.json.JSONObject
7
+ import java.net.URI
8
+ import java.util.UUID
9
+
10
+ object SourceParser {
11
+ private val sourceSerializer = DefaultSourceSerializer()
12
+
13
+ fun stringToJson(jsonString: String?): Source? {
14
+ if (jsonString.isNullOrEmpty()) return null
15
+ if (jsonString.startsWith("http://") || jsonString.startsWith("https://")) {
16
+ return Source {
17
+ url = URI(jsonString)
18
+ }
19
+ }
20
+
21
+ try {
22
+ val jsonSource = JSONObject(jsonString)
23
+ if (jsonSource.has("streamUrl")) {
24
+ return parseContentModel(jsonSource)
25
+ }
26
+ return sourceSerializer.toSource(jsonSource)
27
+
28
+ } catch (e: JSONException) {
29
+ return null
30
+ }
31
+ }
32
+
33
+ private fun parseContentModel(jsonSource: JSONObject): Source? {
34
+ return Source {
35
+ val streamUrl = jsonSource.getString("streamUrl", null)
36
+ if (streamUrl.isNullOrEmpty()) return null
37
+ url = URI(streamUrl)
38
+
39
+ mimeType = jsonSource.getString("streamType", null)
40
+ ?.let { MimeType.parse(it) }
41
+
42
+ jsonSource.getObject("drmConfig") { parseDrmModel(it) }
43
+ ?.also { drm.add(it) }
44
+ }
45
+ }
46
+
47
+ private fun parseDrmModel(jsonDrm: JSONObject): SourceDrm? {
48
+ val drmSchemeUuid = jsonDrm.getString("drmSchemeUuid", null)
49
+ val drmLicenseUri = jsonDrm.getString("drmLicenseUrl", null)
50
+ ?.let { URI(it) }
51
+ val drmCustomData = jsonDrm.getObject("drmCustomData") { parseSourceAuthorization (it) }
52
+ val overrideDrmCallback = jsonDrm.getBoolean("overrideDrmCallback")
53
+
54
+ return if (overrideDrmCallback) {
55
+ SourceDrmOverridden {
56
+ packageName = when (drmSchemeUuid) {
57
+ "widevine", WIDEVINE_UUID -> DrmWidevine.packageName
58
+ "playready", PLAYREADY_UUID -> DrmPlayready.packageName
59
+ else -> null
60
+ }
61
+ licenseServer = drmLicenseUri
62
+ authorization = drmCustomData
63
+ }
64
+ } else {
65
+ when (drmSchemeUuid) {
66
+ "widevine", WIDEVINE_UUID -> SourceDrmWidevine {
67
+ licenseServer = drmLicenseUri
68
+ authorization = drmCustomData
69
+ }
70
+ "playready", PLAYREADY_UUID -> SourceDrmPlayready {
71
+ licenseServer = drmLicenseUri
72
+ authorization = drmCustomData
73
+ }
74
+ else -> null
75
+ }
76
+ }
77
+ }
78
+
79
+ private fun parseSourceAuthorization(jsonMap: JSONObject): SourceAuthorization? {
80
+ return SourceAuthorizationHeaders {
81
+ jsonMap.keys().forEach { key ->
82
+ headers[key] = jsonMap.getString(key)
83
+ }
84
+ }
85
+ }
86
+
87
+ val WIDEVINE_UUID = "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"
88
+ val PLAYREADY_UUID = "9a04f079-9840-4286-ab92-e65be0885f95"
89
+ }
@@ -1,7 +1,5 @@
1
1
  package com.twentyfouri.tvbridge.webview.view
2
2
 
3
- import com.twentyfouri.player.base.PlayerBase
4
-
5
3
  /**
6
4
  * Created by destivar on 15/02/16.
7
5
  */
@@ -9,7 +7,6 @@ interface Mainview {
9
7
  fun loadUrl(url: String?)
10
8
  fun goFullscreen()
11
9
  fun exitFullscreen(width: Int, height: Int, left: Int, top: Int)
12
- fun setUrlToView(urlString: String?)
13
10
  fun setBlackCurtainVisibility(visibility: Int)
14
11
  fun showMessage(message: String?)
15
12
  fun requestAudioFocus(): Int