@24i/smartapps-bigscreen-rnv-build-engine 0.17.6-alpha.19 → 0.17.6-alpha.2
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/README.md +12 -16
- package/dist/src/constants/delopyLivePlatforms.js +1 -2
- package/dist/src/constants/platforms.js +0 -2
- package/dist/src/engine.js +0 -10
- package/dist/src/resolvers/index.js +1 -8
- package/dist/src/resolvers/resolveBaseUrl.js +25 -16
- package/dist/src/resolvers/resolveDeployLocations.js +6 -3
- package/dist/src/resolvers/resolveGenericRnvConfig.js +2 -9
- package/dist/src/resolvers/resolveZippedPlatformBuildsRelativeFilePath.js +1 -25
- package/dist/src/scripts/deployLiveAll.js +2 -2
- package/dist/src/scripts/deployLivePlatform.js +5 -9
- package/dist/src/scripts/release/{appCenter/deployToAppCenter.js → deployToAppCenter.js} +17 -6
- package/dist/src/scripts/release/notifySlack/notifySlack.js +8 -11
- package/dist/src/scripts/release/sentryRelease.js +5 -11
- package/dist/src/scripts/release/urlsMarkdown.js +0 -2
- package/dist/src/scripts/releaseAllWithScheme.js +4 -4
- package/dist/src/sdks/index.js +0 -1
- package/dist/src/sdks/sdk-androidtv/sdkAndroidtv.js +13 -35
- package/dist/src/sdks/sdk-tizen/sdkTizen.js +0 -2
- package/dist/src/sdks/sdk-webos/sdkWebos.js +0 -2
- package/dist/src/sdks/sdk-webpack/sdkWebpack.js +1 -10
- package/dist/src/tasks/deploy/aswS3/deployS3.js +11 -9
- package/dist/src/tasks/deploy/aswS3/distToLiveS3.js +5 -4
- package/dist/src/tasks/deploy/hbbtv/deployHbbtv.js +1 -7
- package/dist/src/tasks/task.rnv.build.js +7 -26
- package/dist/src/tasks/task.rnv.configure.js +0 -2
- package/dist/src/tasks/task.rnv.deploy.js +1 -12
- package/dist/src/tasks/task.rnv.platform.configure.js +1 -33
- package/dist/src/tasks/task.rnv.start.js +0 -2
- package/dist/src/utils/forEachSupportedPlatformFlavour.js +7 -24
- package/dist/src/utils/zipBuildsByPlatforms.js +5 -8
- package/dist/templates/platforms/_shared/webpack.base.js +2 -2
- package/dist/templates/platforms/androidtv/project/amazoniap/build.gradle +2 -2
- package/dist/templates/platforms/androidtv/project/app/build.gradle +21 -17
- package/dist/templates/platforms/androidtv/project/app/proguard-rules.pro +0 -15
- package/dist/templates/platforms/androidtv/project/app/src/bigscreenAppstage/res/raw/configuration.json +2 -1
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeFromJavaScript.kt +58 -4
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeToJavaScript.kt +0 -15
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/configuration/BridgeConfig.kt +1 -2
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ActivityModule.kt +3 -0
- 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/PlayerFactoryExoPlayerCustomized.kt +1 -7
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/SourceDrmOverridden.kt +0 -42
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/jump/JumpAnalytics.kt +211 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/model/MediaEventType.kt +0 -3
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/ContentModelParser.kt +16 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/DeviceInfoParser.kt +22 -0
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/Mainview.kt +3 -0
- 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 +83 -24
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/viewmodel/WebViewModel.kt +111 -48
- package/dist/templates/platforms/androidtv/project/app/src/main/res/layout/activity_web_view.xml +71 -23
- 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 -3
- package/renative.engine.json +0 -2
- package/dist/src/constants/buildProductionPackages.js +0 -10
- package/dist/src/resolvers/resolveProductionZipFileRelativePath.js +0 -35
- package/dist/src/resolvers/resolveS3BucketAppPath.js +0 -15
- package/dist/src/resolvers/resolveSupportedFlavoursForPlatform.js +0 -8
- package/dist/src/resolvers/shared/constructFullUrl.js +0 -25
- package/dist/src/scripts/buildAllWithSchemes.js +0 -88
- package/dist/src/scripts/buildProductionPackagesAll.js +0 -75
- package/dist/src/scripts/release/appCenter/appCenter.js +0 -17
- package/dist/src/scripts/release/appCenter/deployProductionPackagesToAppCenter.js +0 -127
- package/dist/src/scripts/releaseAllWithSchemes.js +0 -158
- package/dist/src/scripts/releaseProductionPackagesAll.js +0 -13
- package/dist/src/utils/copyTheoPlayerLibs.js +0 -48
- package/dist/src/utils/getSafeSchemeString.js +0 -7
- package/dist/src/utils/zipStagingProdBuildsByPlatforms.js +0 -114
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryConfigured.kt +0 -33
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryTheoPlayerCustomized.kt +0 -14
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryVersion.kt +0 -27
- package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/SourceParser.kt +0 -89
|
@@ -2,6 +2,9 @@ package com.twentyfouri.tvbridge.webview.view
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.app.Activity
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.graphics.Bitmap
|
|
7
|
+
import android.graphics.Canvas
|
|
5
8
|
import android.graphics.Point
|
|
6
9
|
import android.media.AudioManager
|
|
7
10
|
import android.media.AudioManager.OnAudioFocusChangeListener
|
|
@@ -11,9 +14,10 @@ import android.text.TextWatcher
|
|
|
11
14
|
import android.util.Log
|
|
12
15
|
import android.view.KeyEvent
|
|
13
16
|
import android.view.View
|
|
14
|
-
import android.view.View.MeasureSpec
|
|
15
17
|
import android.view.WindowManager
|
|
16
18
|
import android.view.inputmethod.InputMethodManager
|
|
19
|
+
import android.webkit.WebChromeClient
|
|
20
|
+
import android.webkit.WebView
|
|
17
21
|
import android.widget.RelativeLayout
|
|
18
22
|
import android.widget.Toast
|
|
19
23
|
import androidx.appcompat.app.AppCompatActivity
|
|
@@ -21,6 +25,7 @@ import androidx.databinding.DataBindingUtil
|
|
|
21
25
|
import androidx.media.AudioAttributesCompat
|
|
22
26
|
import androidx.media.AudioFocusRequestCompat
|
|
23
27
|
import androidx.media.AudioManagerCompat
|
|
28
|
+
import com.twentyfouri.tvbridge.BuildConfig
|
|
24
29
|
import com.twentyfouri.tvbridge.R
|
|
25
30
|
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
26
31
|
import com.twentyfouri.tvbridge.databinding.ActivityWebViewBinding
|
|
@@ -71,14 +76,36 @@ class WebViewActivity : AppCompatActivity(), Mainview {
|
|
|
71
76
|
CookieHandler.setDefault(defaultCookieManager)
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
binding =
|
|
75
|
-
|
|
76
|
-
binding.
|
|
79
|
+
binding = DataBindingUtil.setContentView(this, R.layout.activity_web_view)
|
|
80
|
+
binding.viewModel = viewModel
|
|
81
|
+
binding.exoplayerView.playerFactory = viewModel.playerFactory
|
|
77
82
|
viewModel.attachView(this)
|
|
78
83
|
viewModel.configureWebView(binding.webview)
|
|
79
|
-
viewModel.player = binding.
|
|
84
|
+
viewModel.player = binding.exoplayerView.player
|
|
80
85
|
|
|
81
|
-
|
|
86
|
+
binding.url.addTextChangedListener(object : TextWatcher {
|
|
87
|
+
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
|
88
|
+
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
|
89
|
+
viewModel.appUrl = s.toString()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
override fun afterTextChanged(s: Editable) {}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
val appUrl = config.baseUrl
|
|
96
|
+
if (config.customizableUrl) {
|
|
97
|
+
viewModel.urlSetterVisible = true
|
|
98
|
+
viewModel.appUrl = appUrl
|
|
99
|
+
setUrlToView(appUrl)
|
|
100
|
+
} else {
|
|
101
|
+
viewModel.urlSetterVisible = false
|
|
102
|
+
loadUrl(appUrl)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
binding.root.viewTreeObserver.addOnGlobalFocusChangeListener { oldFocus: View, newFocus: View ->
|
|
106
|
+
Log.v("FOCUS", "global focus changed old = $oldFocus")
|
|
107
|
+
Log.v("FOCUS", "global focus changed new = $newFocus")
|
|
108
|
+
}
|
|
82
109
|
|
|
83
110
|
initialized = true
|
|
84
111
|
}
|
|
@@ -143,12 +170,13 @@ class WebViewActivity : AppCompatActivity(), Mainview {
|
|
|
143
170
|
public override fun onDestroy() {
|
|
144
171
|
if (initialized) {
|
|
145
172
|
viewModel.releasePlayer()
|
|
173
|
+
binding.unbind()
|
|
146
174
|
}
|
|
147
175
|
super.onDestroy()
|
|
148
176
|
}
|
|
149
177
|
|
|
150
178
|
override fun goFullscreen() {
|
|
151
|
-
val layoutParams = binding.
|
|
179
|
+
val layoutParams = binding.exoplayerView.layoutParams as RelativeLayout.LayoutParams
|
|
152
180
|
layoutParams.width = -1
|
|
153
181
|
layoutParams.height = -1
|
|
154
182
|
layoutParams.leftMargin = 0
|
|
@@ -159,12 +187,8 @@ class WebViewActivity : AppCompatActivity(), Mainview {
|
|
|
159
187
|
display.getSize(size)
|
|
160
188
|
val width = size.x
|
|
161
189
|
val height = size.y
|
|
162
|
-
binding.
|
|
163
|
-
binding.
|
|
164
|
-
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
165
|
-
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
|
|
166
|
-
)
|
|
167
|
-
binding.playerView.layout(width, height, 0, 0)
|
|
190
|
+
binding.exoplayerView.layoutParams = layoutParams
|
|
191
|
+
binding.exoplayerView.layout(width, height, 0, 0)
|
|
168
192
|
}
|
|
169
193
|
|
|
170
194
|
override fun launchIapPurchase(sku: String) {
|
|
@@ -172,22 +196,37 @@ class WebViewActivity : AppCompatActivity(), Mainview {
|
|
|
172
196
|
}
|
|
173
197
|
|
|
174
198
|
override fun exitFullscreen(width: Int, height: Int, left: Int, top: Int) {
|
|
175
|
-
val layoutParams = binding.
|
|
199
|
+
val layoutParams = binding.exoplayerView.layoutParams as RelativeLayout.LayoutParams
|
|
176
200
|
layoutParams.width = width
|
|
177
201
|
layoutParams.height = height
|
|
178
202
|
layoutParams.leftMargin = left
|
|
179
203
|
layoutParams.topMargin = top
|
|
180
204
|
|
|
181
205
|
//set the layout inner and outer sizes
|
|
182
|
-
binding.
|
|
183
|
-
binding.
|
|
206
|
+
binding.exoplayerView.layoutParams = layoutParams
|
|
207
|
+
binding.exoplayerView.layout(width, height, left, top)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
override fun setUrlToView(urlString: String?) {
|
|
211
|
+
binding.url.requestFocus()
|
|
212
|
+
binding.url.setText(urlString)
|
|
213
|
+
binding.url.setSelection(urlString?.length ?: 0)
|
|
184
214
|
}
|
|
185
215
|
|
|
186
216
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
|
187
217
|
when (event.keyCode) {
|
|
218
|
+
KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_LEFT -> changeFocus()
|
|
188
219
|
KeyEvent.KEYCODE_DPAD_CENTER -> goToUrl()
|
|
220
|
+
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_BUTTON_B, KeyEvent.KEYCODE_BUTTON_A, KeyEvent.KEYCODE_MENU, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_MEDIA_PAUSE, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> {
|
|
221
|
+
if (!binding.url.hasFocus() && !binding.buttonGo.hasFocus()) {
|
|
222
|
+
// Send these key presses to the WebView, through a JavaScript bridge.
|
|
223
|
+
viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_DOWN)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
189
226
|
else -> {
|
|
190
|
-
|
|
227
|
+
if (!binding.url.hasFocus() && !binding.buttonGo.hasFocus()) {
|
|
228
|
+
viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_DOWN)
|
|
229
|
+
}
|
|
191
230
|
}
|
|
192
231
|
}
|
|
193
232
|
return super.onKeyDown(keyCode, event)
|
|
@@ -215,19 +254,35 @@ class WebViewActivity : AppCompatActivity(), Mainview {
|
|
|
215
254
|
}
|
|
216
255
|
|
|
217
256
|
private fun goToUrl() {
|
|
218
|
-
|
|
257
|
+
if (binding.buttonGo.hasFocus()) {
|
|
258
|
+
viewModel.onClickGo()
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private fun changeFocus() {
|
|
263
|
+
if (binding.url.hasFocus()) {
|
|
264
|
+
binding.buttonGo.requestFocus()
|
|
265
|
+
} else if (binding.buttonGo.hasFocus()) {
|
|
266
|
+
binding.url.requestFocus()
|
|
267
|
+
}
|
|
219
268
|
}
|
|
220
269
|
|
|
221
270
|
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
271
|
+
if (!binding.url.hasFocus() && !binding.buttonGo.hasFocus()) {
|
|
272
|
+
// Send these key presses to the WebView, through a JavaScript bridge.
|
|
273
|
+
viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_UP)
|
|
274
|
+
return true
|
|
275
|
+
}
|
|
276
|
+
return super.onKeyUp(keyCode, event)
|
|
225
277
|
}
|
|
226
278
|
|
|
227
279
|
override fun onKeyLongPress(keyCode: Int, event: KeyEvent): Boolean {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
280
|
+
if (!binding.url.hasFocus() && !binding.buttonGo.hasFocus()) {
|
|
281
|
+
// Send these key presses to the WebView, through a JavaScript bridge.
|
|
282
|
+
viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_PRESS)
|
|
283
|
+
return true
|
|
284
|
+
}
|
|
285
|
+
return super.onKeyLongPress(keyCode, event)
|
|
231
286
|
}
|
|
232
287
|
|
|
233
288
|
override fun loadUrl(url: String?) {
|
|
@@ -239,6 +294,10 @@ class WebViewActivity : AppCompatActivity(), Mainview {
|
|
|
239
294
|
}
|
|
240
295
|
}
|
|
241
296
|
|
|
297
|
+
override fun onBackPressed() {
|
|
298
|
+
super.onBackPressed()
|
|
299
|
+
}
|
|
300
|
+
|
|
242
301
|
companion object {
|
|
243
302
|
private val defaultCookieManager: CookieManager = CookieManager().apply {
|
|
244
303
|
setCookiePolicy(CookiePolicy.ACCEPT_ALL)
|
|
@@ -5,6 +5,7 @@ import android.content.Context
|
|
|
5
5
|
import android.content.Intent
|
|
6
6
|
import android.graphics.Bitmap
|
|
7
7
|
import android.graphics.Canvas
|
|
8
|
+
import android.net.Uri
|
|
8
9
|
import android.os.Build
|
|
9
10
|
import android.util.Log
|
|
10
11
|
import android.view.KeyEvent
|
|
@@ -12,9 +13,15 @@ import android.view.View
|
|
|
12
13
|
import android.webkit.CookieManager
|
|
13
14
|
import android.webkit.WebChromeClient
|
|
14
15
|
import android.webkit.WebView
|
|
16
|
+
import androidx.databinding.BaseObservable
|
|
17
|
+
import androidx.databinding.Bindable
|
|
18
|
+
import com.google.android.exoplayer2.C
|
|
19
|
+
import com.google.android.exoplayer2.SeekParameters
|
|
15
20
|
import com.google.gson.JsonArray
|
|
16
21
|
import com.google.gson.JsonObject
|
|
17
22
|
import com.twentyfouri.player.base.*
|
|
23
|
+
import com.twentyfouri.player.exoplayer.PlayerExoPlayer
|
|
24
|
+
import com.twentyfouri.tvbridge.BR
|
|
18
25
|
import com.twentyfouri.tvbridge.BuildConfig
|
|
19
26
|
import com.twentyfouri.tvbridge.Flavor
|
|
20
27
|
import com.twentyfouri.tvbridge.bridge.BridgeFromJavaScript
|
|
@@ -22,12 +29,14 @@ import com.twentyfouri.tvbridge.bridge.BridgeToJavaScript
|
|
|
22
29
|
import com.twentyfouri.tvbridge.common.*
|
|
23
30
|
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
24
31
|
import com.twentyfouri.tvbridge.global.utils.LocalStorage
|
|
25
|
-
import com.twentyfouri.tvbridge.global.utils.PlayerFactoryVersion
|
|
26
32
|
import com.twentyfouri.tvbridge.global.utils.SourceDrmOverridden
|
|
33
|
+
import com.twentyfouri.tvbridge.jump.JumpAnalytics
|
|
27
34
|
import com.twentyfouri.tvbridge.webview.client.BridgeWebView
|
|
28
35
|
import com.twentyfouri.tvbridge.webview.client.BridgeWebViewClient
|
|
29
36
|
import com.twentyfouri.tvbridge.webview.client.BridgeWebViewClient.BridgeWebViewClientCallback
|
|
30
37
|
import com.twentyfouri.tvbridge.webview.model.AnalyticsPlaybackInfo
|
|
38
|
+
import com.twentyfouri.tvbridge.webview.model.ContentModel
|
|
39
|
+
import com.twentyfouri.tvbridge.webview.model.DrmModel
|
|
31
40
|
import com.twentyfouri.tvbridge.webview.model.MediaEventType
|
|
32
41
|
import com.twentyfouri.tvbridge.webview.view.Mainview
|
|
33
42
|
import com.twentyfouri.tvbridge.webview.view.PlayerCache
|
|
@@ -35,6 +44,7 @@ import org.json.JSONArray
|
|
|
35
44
|
import org.json.JSONException
|
|
36
45
|
import org.json.JSONObject
|
|
37
46
|
import java.net.NetworkInterface
|
|
47
|
+
import java.net.URI
|
|
38
48
|
import javax.inject.Inject
|
|
39
49
|
|
|
40
50
|
/**
|
|
@@ -46,7 +56,7 @@ class WebViewModel @Inject constructor(
|
|
|
46
56
|
private val config: BridgeConfig,
|
|
47
57
|
private val iapService: IapService,
|
|
48
58
|
val playerFactory: PlayerFactoryBase
|
|
49
|
-
) : EventListener {
|
|
59
|
+
) : BaseObservable(), EventListener {
|
|
50
60
|
var player: PlayerBase? = null
|
|
51
61
|
private var view: Mainview? = null
|
|
52
62
|
private val jsBridge = BridgeToJavaScript(config) { s: String? ->
|
|
@@ -54,9 +64,12 @@ class WebViewModel @Inject constructor(
|
|
|
54
64
|
}
|
|
55
65
|
private val iapCallback = InnerIapCallback()
|
|
56
66
|
private val playerCache = PlayerCache()
|
|
67
|
+
private val jumpAnalytics = JumpAnalytics()
|
|
57
68
|
|
|
58
|
-
private var
|
|
69
|
+
private var contentModel: ContentModel? = null
|
|
59
70
|
|
|
71
|
+
val videoTrack: VideoTrack?
|
|
72
|
+
get() = player?.selectedVideoTrack
|
|
60
73
|
val audioTrack: AudioTrack?
|
|
61
74
|
get() = player?.selectedAudioTrack
|
|
62
75
|
val subtitleTrack: TextTrack?
|
|
@@ -64,6 +77,17 @@ class WebViewModel @Inject constructor(
|
|
|
64
77
|
|
|
65
78
|
var appUrl: String? = null
|
|
66
79
|
|
|
80
|
+
var urlSetterVisible: Boolean = false
|
|
81
|
+
set(value) {
|
|
82
|
+
if (field == value) return
|
|
83
|
+
field = value
|
|
84
|
+
notifyPropertyChanged(BR.urlSetterVisibility)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@get:Bindable
|
|
88
|
+
val urlSetterVisibility: Int
|
|
89
|
+
get() = if (urlSetterVisible) View.VISIBLE else View.GONE
|
|
90
|
+
|
|
67
91
|
fun attachView(view: Mainview?) {
|
|
68
92
|
this.view = view
|
|
69
93
|
if (view != null) {
|
|
@@ -118,42 +142,52 @@ class WebViewModel @Inject constructor(
|
|
|
118
142
|
|
|
119
143
|
fun onClickGo() {
|
|
120
144
|
view?.loadUrl(appUrl)
|
|
145
|
+
urlSetterVisible = false
|
|
121
146
|
if (BuildConfig.DEBUG) {
|
|
122
147
|
view?.hideKeyboard()
|
|
123
148
|
}
|
|
124
149
|
}
|
|
125
150
|
|
|
126
|
-
fun setVideo(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
151
|
+
fun setVideo(contentModel: ContentModel) {
|
|
152
|
+
logContentModel(contentModel)
|
|
153
|
+
playDirectly(contentModel)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private fun logContentModel(contentModel: ContentModel) {
|
|
157
|
+
Log.i("BridgeVideo", "Url: " + contentModel.streamUrl)
|
|
158
|
+
val drmModel = contentModel.drmModel
|
|
159
|
+
if (drmModel != null) {
|
|
160
|
+
Log.i("BridgeVideo", "DRM: " + drmModel.drmSchemeUuid)
|
|
161
|
+
Log.i("BridgeVideo", "LicenseUrl: " + drmModel.drmLicenseUrl)
|
|
130
162
|
}
|
|
131
|
-
logSource(adaptedSource)
|
|
132
|
-
playDirectly(adaptedSource)
|
|
133
163
|
}
|
|
134
164
|
|
|
135
|
-
private fun
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
is SourceDrmOverridden -> {
|
|
147
|
-
Log.i("BridgeVideo", "DRM: " + drmModel.packageName)
|
|
148
|
-
Log.i("BridgeVideo", "LicenseUrl: " + drmModel.licenseServer)
|
|
149
|
-
}
|
|
165
|
+
private fun playInExoPlayerDemoApp(contentModel: ContentModel) {
|
|
166
|
+
val intent = Intent("com.google.android.exoplayer.demo.action.VIEW", Uri.parse(contentModel.streamUrl))
|
|
167
|
+
val drmModel = contentModel.drmModel
|
|
168
|
+
if (drmModel != null) {
|
|
169
|
+
intent.putExtra("drm_scheme", drmModel.drmSchemeUuid)
|
|
170
|
+
intent.putExtra("drm_license_url", drmModel.drmLicenseUrl)
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
context.startActivity(intent)
|
|
174
|
+
} catch (e: Exception) {
|
|
175
|
+
Log.w("WebViewModel", "Failed to start ExoPlayer demo app", e)
|
|
150
176
|
}
|
|
151
177
|
}
|
|
152
178
|
|
|
153
|
-
private fun playDirectly(
|
|
154
|
-
this.
|
|
179
|
+
private fun playDirectly(contentModel: ContentModel) {
|
|
180
|
+
this.contentModel = contentModel
|
|
181
|
+
(player as? PlayerExoPlayer)?.exoPlayer?.also { exoPlayer ->
|
|
182
|
+
jumpAnalytics.setVideoPlayer(exoPlayer)
|
|
183
|
+
exoPlayer.setSeekParameters(SeekParameters.CLOSEST_SYNC)
|
|
184
|
+
}
|
|
155
185
|
player?.also { player ->
|
|
156
|
-
player.source =
|
|
186
|
+
player.source = Source {
|
|
187
|
+
url = contentModel.streamUrl?.let { URI(it) }
|
|
188
|
+
mimeType = detectMimeType(contentModel)
|
|
189
|
+
contentModel.drmModel?.let { buildDrm(it) }?.also { drm.add(it) }
|
|
190
|
+
}
|
|
157
191
|
|
|
158
192
|
if (isLowEndDevice) {
|
|
159
193
|
player.trackRestrictions = player.trackRestrictions.buildUpon {
|
|
@@ -173,6 +207,43 @@ class WebViewModel @Inject constructor(
|
|
|
173
207
|
}
|
|
174
208
|
}
|
|
175
209
|
|
|
210
|
+
private fun detectMimeType(contentModel: ContentModel) =
|
|
211
|
+
when (contentModel.streamType) {
|
|
212
|
+
null, "" -> null
|
|
213
|
+
".mpd", "mpd", "dash" -> ManifestDash.mimeType
|
|
214
|
+
".ism", "ism", "ss" -> ManifestSmoothStreaming.mimeType
|
|
215
|
+
".m3u8", "m3u8", "hls" -> ManifestHls.mimeType
|
|
216
|
+
else -> null
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private fun buildDrm(drmModel: DrmModel): SourceDrm? {
|
|
220
|
+
val drmScheme = drmModel.drmSchemeUuid
|
|
221
|
+
val useOverride = drmModel.overrideDrmCallback ?: config.drm.shouldOverrideDrmCallback()
|
|
222
|
+
val useWidevine = drmScheme == "widevine" || drmScheme == C.WIDEVINE_UUID.toString()
|
|
223
|
+
val usePlayReady = drmScheme == "playready" || drmScheme == C.PLAYREADY_UUID.toString()
|
|
224
|
+
return when {
|
|
225
|
+
drmScheme == null -> null
|
|
226
|
+
useOverride -> SourceDrmOverridden {
|
|
227
|
+
packageName = when {
|
|
228
|
+
useWidevine -> DrmWidevine.packageName
|
|
229
|
+
usePlayReady -> DrmPlayready.packageName
|
|
230
|
+
else -> ""
|
|
231
|
+
}
|
|
232
|
+
licenseServer = drmModel.drmLicenseUrl?.let { URI(it) }
|
|
233
|
+
forceLicenseServer = true
|
|
234
|
+
}
|
|
235
|
+
useWidevine -> SourceDrmWidevine {
|
|
236
|
+
licenseServer = drmModel.drmLicenseUrl?.let { URI(it) }
|
|
237
|
+
forceLicenseServer = true
|
|
238
|
+
}
|
|
239
|
+
usePlayReady -> SourceDrmWidevine {
|
|
240
|
+
licenseServer = drmModel.drmLicenseUrl?.let { URI(it) }
|
|
241
|
+
forceLicenseServer = true
|
|
242
|
+
}
|
|
243
|
+
else -> SourceDrmUnrecognized(drmScheme)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
176
247
|
private val isLowEndDevice: Boolean
|
|
177
248
|
get() = when (Build.MODEL) {
|
|
178
249
|
"AFTB" -> true
|
|
@@ -185,9 +256,9 @@ class WebViewModel @Inject constructor(
|
|
|
185
256
|
}
|
|
186
257
|
|
|
187
258
|
fun resumePlayer() {
|
|
188
|
-
val
|
|
189
|
-
if (playerCache.loadFromCache &&
|
|
190
|
-
setVideo(
|
|
259
|
+
val savedContentModel = playerCache.savedContentModel
|
|
260
|
+
if (playerCache.loadFromCache && savedContentModel != null && playerCache.savedPlayerState !== PlayerCache.PlayerState.PAUSED) {
|
|
261
|
+
setVideo(savedContentModel)
|
|
191
262
|
var position = playerCache.savedPlayerPosition
|
|
192
263
|
val player = this.player ?: return
|
|
193
264
|
if (player.live) {
|
|
@@ -212,24 +283,26 @@ class WebViewModel @Inject constructor(
|
|
|
212
283
|
|
|
213
284
|
fun stopPlayer() {
|
|
214
285
|
view?.setBlackCurtainVisibility(View.VISIBLE)
|
|
215
|
-
|
|
286
|
+
contentModel = null
|
|
216
287
|
|
|
217
288
|
player?.also { player ->
|
|
218
289
|
player.removeEventListener(Event.ALL, this)
|
|
219
290
|
player.unload()
|
|
291
|
+
jumpAnalytics.setVideoPlayer(null)
|
|
220
292
|
}
|
|
221
293
|
}
|
|
222
294
|
|
|
223
295
|
fun releasePlayer() {
|
|
224
296
|
val player = this.player ?: return
|
|
225
|
-
if (
|
|
297
|
+
if (contentModel != null) {
|
|
226
298
|
playerCache.loadFromCache = true
|
|
227
|
-
playerCache.
|
|
299
|
+
playerCache.savedContentModel = contentModel
|
|
228
300
|
playerCache.savedPlayerDuration = player.duration
|
|
229
301
|
playerCache.savedPlayerPosition = player.currentTime
|
|
230
302
|
playerCache.savedPlayerState = if (player.playing) PlayerCache.PlayerState.PLAYING else PlayerCache.PlayerState.PAUSED
|
|
231
303
|
}
|
|
232
304
|
player.unload()
|
|
305
|
+
jumpAnalytics.setVideoPlayer(null)
|
|
233
306
|
}
|
|
234
307
|
|
|
235
308
|
val currentPosition: Double
|
|
@@ -244,7 +317,7 @@ class WebViewModel @Inject constructor(
|
|
|
244
317
|
val isPlayerPlaying: Boolean
|
|
245
318
|
get() = player?.playing == true
|
|
246
319
|
val isInPlayer: Boolean
|
|
247
|
-
get() = player != null &&
|
|
320
|
+
get() = player != null && contentModel != null
|
|
248
321
|
|
|
249
322
|
fun loadUrl(url: String?) {
|
|
250
323
|
view?.loadUrl(url)
|
|
@@ -286,7 +359,6 @@ class WebViewModel @Inject constructor(
|
|
|
286
359
|
}
|
|
287
360
|
is LoadedMetadataEvent -> {
|
|
288
361
|
jsBridge.bridgeAndroidToJavaScript_MediaEvent(MediaEventType.LOADEDMETADATA)
|
|
289
|
-
jsBridge.bridgeAndroidToJavaScript_MediaTrackEvent(MediaEventType.TRACKS_CHANGED, player.audioTracks, player.textTracks)
|
|
290
362
|
}
|
|
291
363
|
is CanPlayEvent -> {
|
|
292
364
|
jsBridge.bridgeAndroidToJavaScript_MediaEvent(MediaEventType.CANPLAY)
|
|
@@ -317,21 +389,13 @@ class WebViewModel @Inject constructor(
|
|
|
317
389
|
jsBridge.bridgeAndroidToJavaScript_MediaEvent(MediaEventType.PAUSE)
|
|
318
390
|
}
|
|
319
391
|
}
|
|
392
|
+
is LoadedMetadataEvent,
|
|
320
393
|
is AddAudioTrackEvent, is AddTextTrackEvent,
|
|
321
394
|
is RemoveAudioTrackEvent, is RemoveTextTrackEvent,
|
|
322
395
|
is ChangeAudioTrackEvent, is ChangeTextTrackEvent -> {
|
|
323
396
|
Log.d("WebViewModel", "onTracksChanged: audio=$audioTrack subtitle=$subtitleTrack")
|
|
324
397
|
jsBridge.bridgeAndroidToJavaScript_MediaTrackEvent(MediaEventType.TRACKS_CHANGED, player.audioTracks, player.textTracks)
|
|
325
398
|
}
|
|
326
|
-
is AdBreakStartedEvent -> {
|
|
327
|
-
jsBridge.bridgeAndroidToJavaScript_MediaEvent(MediaEventType.AD_BREAK_START)
|
|
328
|
-
}
|
|
329
|
-
is AdBreakEndedEvent -> {
|
|
330
|
-
jsBridge.bridgeAndroidToJavaScript_MediaEvent(MediaEventType.AD_BREAK_END)
|
|
331
|
-
}
|
|
332
|
-
is AdBreaksRescheduledEvent -> {
|
|
333
|
-
jsBridge.bridgeAndroidToJavaScript_MediaAdBreaksEvent(MediaEventType.AD_BREAKS_RESCHEDULED, player.timeline)
|
|
334
|
-
}
|
|
335
399
|
}
|
|
336
400
|
}
|
|
337
401
|
|
|
@@ -360,7 +424,9 @@ class WebViewModel @Inject constructor(
|
|
|
360
424
|
}
|
|
361
425
|
|
|
362
426
|
fun setPlaybackInfo(playbackInfo: AnalyticsPlaybackInfo) {
|
|
363
|
-
|
|
427
|
+
if ("JUMP" == playbackInfo.name) {
|
|
428
|
+
jumpAnalytics.setPlaybackInfo(playbackInfo)
|
|
429
|
+
}
|
|
364
430
|
}
|
|
365
431
|
|
|
366
432
|
fun showMessage(message: String?) {
|
|
@@ -458,14 +524,11 @@ class WebViewModel @Inject constructor(
|
|
|
458
524
|
fun detectDeviceInfo(): JSONObject {
|
|
459
525
|
val deviceInfo = JSONObject()
|
|
460
526
|
try {
|
|
461
|
-
val engineVersion = PlayerFactoryVersion.from(playerFactory)
|
|
462
527
|
deviceInfo.put("deviceBrand", Build.MANUFACTURER)
|
|
463
528
|
deviceInfo.put("deviceModel", Build.MODEL)
|
|
464
529
|
deviceInfo.put("osVersion", Build.VERSION.RELEASE)
|
|
465
530
|
deviceInfo.put("appFlavor", BuildConfig.FLAVOR)
|
|
466
531
|
deviceInfo.put("appVersion", BuildConfig.VERSION_NAME)
|
|
467
|
-
deviceInfo.put("engineName", engineVersion.engineName)
|
|
468
|
-
deviceInfo.put("engineVersion", engineVersion.engineVersion)
|
|
469
532
|
|
|
470
533
|
val drmKeySystems = mutableSetOf<String>()
|
|
471
534
|
playerFactory.getSupportedFormats(context).manifest.forEach { manifest ->
|
package/dist/templates/platforms/androidtv/project/app/src/main/res/layout/activity_web_view.xml
CHANGED
|
@@ -1,28 +1,76 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
android:background="@android:color/black">
|
|
1
|
+
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
3
|
+
xmlns:tools="http://schemas.android.com/tools">
|
|
5
4
|
|
|
6
|
-
<
|
|
7
|
-
android:id="@+id/player_view"
|
|
8
|
-
android:layout_width="match_parent"
|
|
9
|
-
android:layout_height="match_parent" />
|
|
5
|
+
<data>
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
android:background="@android:color/black" />
|
|
7
|
+
<variable
|
|
8
|
+
name="viewModel"
|
|
9
|
+
type="com.twentyfouri.tvbridge.webview.viewmodel.WebViewModel" />
|
|
10
|
+
</data>
|
|
16
11
|
|
|
17
|
-
<
|
|
18
|
-
android:id="@+id/webview"
|
|
12
|
+
<RelativeLayout
|
|
19
13
|
android:layout_width="match_parent"
|
|
20
14
|
android:layout_height="match_parent"
|
|
21
|
-
android:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
android:background="@android:color/black"
|
|
16
|
+
tools:context=".webview.ui.view.WebViewActivity">
|
|
17
|
+
|
|
18
|
+
<com.twentyfouri.player.base.PlayerView
|
|
19
|
+
android:id="@+id/exoplayer_view"
|
|
20
|
+
android:layout_width="match_parent"
|
|
21
|
+
android:layout_height="match_parent" />
|
|
22
|
+
|
|
23
|
+
<View
|
|
24
|
+
android:id="@+id/black_curtain"
|
|
25
|
+
android:layout_width="match_parent"
|
|
26
|
+
android:layout_height="match_parent"
|
|
27
|
+
android:background="@android:color/black" />
|
|
28
|
+
|
|
29
|
+
<LinearLayout
|
|
30
|
+
android:id="@+id/url_setter"
|
|
31
|
+
android:layout_width="match_parent"
|
|
32
|
+
android:layout_height="wrap_content"
|
|
33
|
+
android:layout_centerInParent="true"
|
|
34
|
+
android:layout_margin="80dp"
|
|
35
|
+
android:orientation="vertical"
|
|
36
|
+
app:visibility="@{viewModel.urlSetterVisibility}">
|
|
37
|
+
|
|
38
|
+
<EditText
|
|
39
|
+
android:id="@+id/url"
|
|
40
|
+
android:layout_width="match_parent"
|
|
41
|
+
android:layout_height="wrap_content"
|
|
42
|
+
android:nextFocusUp="@+id/url"
|
|
43
|
+
android:nextFocusLeft="@+id/url"
|
|
44
|
+
android:nextFocusRight="@+id/url"
|
|
45
|
+
android:textColor="@android:color/white"/>
|
|
46
|
+
|
|
47
|
+
<Button
|
|
48
|
+
android:id="@+id/button_go"
|
|
49
|
+
android:layout_width="100dp"
|
|
50
|
+
android:layout_height="wrap_content"
|
|
51
|
+
android:background="@drawable/button_focus"
|
|
52
|
+
android:textColor="@android:color/black"
|
|
53
|
+
android:nextFocusDown="@+id/button_go"
|
|
54
|
+
android:nextFocusLeft="@+id/button_go"
|
|
55
|
+
android:nextFocusRight="@+id/button_go"
|
|
56
|
+
android:onClick="@{() -> viewModel.onClickGo()}"
|
|
57
|
+
android:text="GO" />
|
|
58
|
+
|
|
59
|
+
</LinearLayout>
|
|
60
|
+
|
|
61
|
+
<com.twentyfouri.tvbridge.webview.client.BridgeWebView
|
|
62
|
+
android:id="@+id/webview"
|
|
63
|
+
android:layout_width="match_parent"
|
|
64
|
+
android:layout_height="match_parent"
|
|
65
|
+
android:layout_alignParentBottom="true"
|
|
66
|
+
android:layout_alignParentEnd="true"
|
|
67
|
+
android:layout_alignParentStart="true"
|
|
68
|
+
android:layout_alignParentTop="true"
|
|
69
|
+
android:background="@android:color/transparent"
|
|
70
|
+
android:visibility="gone"/>
|
|
71
|
+
|
|
72
|
+
</RelativeLayout>
|
|
73
|
+
|
|
74
|
+
</layout>
|
|
75
|
+
|
|
76
|
+
|
|
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
|
|
|
2
2
|
apply plugin: 'kotlin-android'
|
|
3
3
|
|
|
4
4
|
android {
|
|
5
|
-
compileSdkVersion
|
|
5
|
+
compileSdkVersion 31
|
|
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 30
|
|
15
15
|
|
|
16
16
|
versionCode 1
|
|
17
17
|
versionName "1.0"
|
|
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
|
|
|
2
2
|
apply plugin: 'kotlin-android'
|
|
3
3
|
|
|
4
4
|
android {
|
|
5
|
-
compileSdkVersion
|
|
5
|
+
compileSdkVersion 31
|
|
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 30
|
|
15
15
|
|
|
16
16
|
versionCode 1
|
|
17
17
|
versionName "1.0"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@24i/smartapps-bigscreen-rnv-build-engine",
|
|
3
|
-
"version": "0.17.6-alpha.
|
|
3
|
+
"version": "0.17.6-alpha.2",
|
|
4
4
|
"description": "Package with build engine for SmartApps BIGscreen projects...",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -35,11 +35,9 @@
|
|
|
35
35
|
}
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"fs-extra": "11.1.1",
|
|
39
38
|
"xml2js": "^0.4.23"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@types/fs-extra": "11.0.1",
|
|
43
41
|
"@types/inquirer": "8.2.1",
|
|
44
42
|
"@types/ip": "1.1.0",
|
|
45
43
|
"@types/mini-css-extract-plugin": "1.4.3",
|