@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.
- package/dist/src/resolvers/resolveBaseUrl.js +3 -1
- package/dist/src/sdks/sdk-androidtv/sdkAndroidtv.js +22 -8
- package/dist/templates/platforms/androidtv/project/amazoniap/build.gradle +2 -2
- package/dist/templates/platforms/androidtv/project/app/build.gradle +17 -21
- package/dist/templates/platforms/androidtv/project/app/proguard-rules.pro +15 -0
- package/dist/templates/platforms/androidtv/project/app/src/bigscreenAppstage/res/raw/configuration.json +1 -2
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeFromJavaScript.kt +4 -58
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeToJavaScript.kt +15 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/configuration/BridgeConfig.kt +2 -1
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ActivityModule.kt +0 -3
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ApplicationModule.kt +2 -2
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/PerActivity.kt +0 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryConfigured.kt +33 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryExoPlayerCustomized.kt +7 -1
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryTheoPlayerCustomized.kt +14 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryVersion.kt +27 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/SourceDrmOverridden.kt +42 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/model/MediaEventType.kt +3 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/SourceParser.kt +89 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/Mainview.kt +0 -3
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/PlayerCache.kt +2 -2
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/WebViewActivity.kt +24 -83
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/viewmodel/WebViewModel.kt +48 -111
- package/dist/templates/platforms/androidtv/project/app/src/main/res/layout/activity_web_view.xml +23 -71
- package/dist/templates/platforms/androidtv/project/common/build.gradle +2 -2
- package/dist/templates/platforms/androidtv/project/googleiap/build.gradle +2 -2
- package/package.json +1 -1
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/jump/JumpAnalytics.kt +0 -211
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/ContentModelParser.kt +0 -16
- 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
|
|
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',
|
|
143
|
-
const compileSdkVersion = rnv_1.Common.getConfigProp(c, c.platform, 'compileSdkVersion',
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
190
|
-
rnv_1.FileUtils.writeCleanFile(
|
|
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
|
|
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
|
|
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
|
@@ -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.
|
|
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
|
-
|
|
73
|
-
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
49
|
+
PlayerFactoryConfigured.buildFactory(config)
|
|
50
50
|
|
|
51
51
|
}
|
|
File without changes
|
|
@@ -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
|