@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.
Files changed (75) hide show
  1. package/README.md +12 -16
  2. package/dist/src/constants/delopyLivePlatforms.js +1 -2
  3. package/dist/src/constants/platforms.js +0 -2
  4. package/dist/src/engine.js +0 -10
  5. package/dist/src/resolvers/index.js +1 -8
  6. package/dist/src/resolvers/resolveBaseUrl.js +25 -16
  7. package/dist/src/resolvers/resolveDeployLocations.js +6 -3
  8. package/dist/src/resolvers/resolveGenericRnvConfig.js +2 -9
  9. package/dist/src/resolvers/resolveZippedPlatformBuildsRelativeFilePath.js +1 -25
  10. package/dist/src/scripts/deployLiveAll.js +2 -2
  11. package/dist/src/scripts/deployLivePlatform.js +5 -9
  12. package/dist/src/scripts/release/{appCenter/deployToAppCenter.js → deployToAppCenter.js} +17 -6
  13. package/dist/src/scripts/release/notifySlack/notifySlack.js +8 -11
  14. package/dist/src/scripts/release/sentryRelease.js +5 -11
  15. package/dist/src/scripts/release/urlsMarkdown.js +0 -2
  16. package/dist/src/scripts/releaseAllWithScheme.js +4 -4
  17. package/dist/src/sdks/index.js +0 -1
  18. package/dist/src/sdks/sdk-androidtv/sdkAndroidtv.js +13 -35
  19. package/dist/src/sdks/sdk-tizen/sdkTizen.js +0 -2
  20. package/dist/src/sdks/sdk-webos/sdkWebos.js +0 -2
  21. package/dist/src/sdks/sdk-webpack/sdkWebpack.js +1 -10
  22. package/dist/src/tasks/deploy/aswS3/deployS3.js +11 -9
  23. package/dist/src/tasks/deploy/aswS3/distToLiveS3.js +5 -4
  24. package/dist/src/tasks/deploy/hbbtv/deployHbbtv.js +1 -7
  25. package/dist/src/tasks/task.rnv.build.js +7 -26
  26. package/dist/src/tasks/task.rnv.configure.js +0 -2
  27. package/dist/src/tasks/task.rnv.deploy.js +1 -12
  28. package/dist/src/tasks/task.rnv.platform.configure.js +1 -33
  29. package/dist/src/tasks/task.rnv.start.js +0 -2
  30. package/dist/src/utils/forEachSupportedPlatformFlavour.js +7 -24
  31. package/dist/src/utils/zipBuildsByPlatforms.js +5 -8
  32. package/dist/templates/platforms/_shared/webpack.base.js +2 -2
  33. package/dist/templates/platforms/androidtv/project/amazoniap/build.gradle +2 -2
  34. package/dist/templates/platforms/androidtv/project/app/build.gradle +21 -17
  35. package/dist/templates/platforms/androidtv/project/app/proguard-rules.pro +0 -15
  36. package/dist/templates/platforms/androidtv/project/app/src/bigscreenAppstage/res/raw/configuration.json +2 -1
  37. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeFromJavaScript.kt +58 -4
  38. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/bridge/BridgeToJavaScript.kt +0 -15
  39. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/configuration/BridgeConfig.kt +1 -2
  40. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ActivityModule.kt +3 -0
  41. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/ApplicationModule.kt +2 -2
  42. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/di/PerActivity.kt +0 -0
  43. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryExoPlayerCustomized.kt +1 -7
  44. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/SourceDrmOverridden.kt +0 -42
  45. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/jump/JumpAnalytics.kt +211 -0
  46. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/model/MediaEventType.kt +0 -3
  47. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/ContentModelParser.kt +16 -0
  48. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/parser/DeviceInfoParser.kt +22 -0
  49. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/Mainview.kt +3 -0
  50. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/PlayerCache.kt +2 -2
  51. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/view/WebViewActivity.kt +83 -24
  52. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/webview/viewmodel/WebViewModel.kt +111 -48
  53. package/dist/templates/platforms/androidtv/project/app/src/main/res/layout/activity_web_view.xml +71 -23
  54. package/dist/templates/platforms/androidtv/project/common/build.gradle +2 -2
  55. package/dist/templates/platforms/androidtv/project/googleiap/build.gradle +2 -2
  56. package/package.json +1 -3
  57. package/renative.engine.json +0 -2
  58. package/dist/src/constants/buildProductionPackages.js +0 -10
  59. package/dist/src/resolvers/resolveProductionZipFileRelativePath.js +0 -35
  60. package/dist/src/resolvers/resolveS3BucketAppPath.js +0 -15
  61. package/dist/src/resolvers/resolveSupportedFlavoursForPlatform.js +0 -8
  62. package/dist/src/resolvers/shared/constructFullUrl.js +0 -25
  63. package/dist/src/scripts/buildAllWithSchemes.js +0 -88
  64. package/dist/src/scripts/buildProductionPackagesAll.js +0 -75
  65. package/dist/src/scripts/release/appCenter/appCenter.js +0 -17
  66. package/dist/src/scripts/release/appCenter/deployProductionPackagesToAppCenter.js +0 -127
  67. package/dist/src/scripts/releaseAllWithSchemes.js +0 -158
  68. package/dist/src/scripts/releaseProductionPackagesAll.js +0 -13
  69. package/dist/src/utils/copyTheoPlayerLibs.js +0 -48
  70. package/dist/src/utils/getSafeSchemeString.js +0 -7
  71. package/dist/src/utils/zipStagingProdBuildsByPlatforms.js +0 -114
  72. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryConfigured.kt +0 -33
  73. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryTheoPlayerCustomized.kt +0 -14
  74. package/dist/templates/platforms/androidtv/project/app/src/main/java/com/twentyfouri/tvbridge/global/utils/PlayerFactoryVersion.kt +0 -27
  75. 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 = ActivityWebViewBinding.inflate(layoutInflater)
75
- setContentView(binding.root)
76
- binding.playerView.playerFactory = viewModel.playerFactory
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.playerView.player
84
+ viewModel.player = binding.exoplayerView.player
80
85
 
81
- loadUrl(config.baseUrl)
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.playerView.layoutParams as RelativeLayout.LayoutParams
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.playerView.layoutParams = layoutParams
163
- binding.playerView.measure(
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.playerView.layoutParams as RelativeLayout.LayoutParams
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.playerView.layoutParams = layoutParams
183
- binding.playerView.layout(width, height, left, top)
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
- viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_DOWN)
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
- viewModel.onClickGo()
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
- // Send these key presses to the WebView, through a JavaScript bridge.
223
- viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_UP)
224
- return true
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
- // Send these key presses to the WebView, through a JavaScript bridge.
229
- viewModel.sendKeyCode(event.keyCode, MediaEventType.KEY_PRESS)
230
- return true
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 source: Source? = null
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(source: Source) {
127
- var adaptedSource = source
128
- if (config.drm.shouldOverrideDrmCallback()) {
129
- adaptedSource = SourceDrmOverridden.replaceSource(adaptedSource)
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 logSource(source: Source) {
136
- Log.i("BridgeVideo", "Url: ${source.url}")
137
- when (val drmModel = source.drm.firstOrNull()) {
138
- is SourceDrmWidevine -> {
139
- Log.i("BridgeVideo", "DRM: " + drmModel.packageName)
140
- Log.i("BridgeVideo", "LicenseUrl: " + drmModel.licenseServer)
141
- }
142
- is SourceDrmPlayready -> {
143
- Log.i("BridgeVideo", "DRM: " + drmModel.packageName)
144
- Log.i("BridgeVideo", "LicenseUrl: " + drmModel.licenseServer)
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(source: Source) {
154
- this.source = source
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 = 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 savedSource = playerCache.savedSource
189
- if (playerCache.loadFromCache && savedSource != null && playerCache.savedPlayerState !== PlayerCache.PlayerState.PAUSED) {
190
- setVideo(savedSource)
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
- source = null
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 (source != null) {
297
+ if (contentModel != null) {
226
298
  playerCache.loadFromCache = true
227
- playerCache.savedSource = source
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 && source != 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
- // previously used for Jump analytics, not supported with THEO
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 ->
@@ -1,28 +1,76 @@
1
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2
- android:layout_width="match_parent"
3
- android:layout_height="match_parent"
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
- <com.twentyfouri.player.base.PlayerView
7
- android:id="@+id/player_view"
8
- android:layout_width="match_parent"
9
- android:layout_height="match_parent" />
5
+ <data>
10
6
 
11
- <View
12
- android:id="@+id/black_curtain"
13
- android:layout_width="match_parent"
14
- android:layout_height="match_parent"
15
- android:background="@android:color/black" />
7
+ <variable
8
+ name="viewModel"
9
+ type="com.twentyfouri.tvbridge.webview.viewmodel.WebViewModel" />
10
+ </data>
16
11
 
17
- <com.twentyfouri.tvbridge.webview.client.BridgeWebView
18
- android:id="@+id/webview"
12
+ <RelativeLayout
19
13
  android:layout_width="match_parent"
20
14
  android:layout_height="match_parent"
21
- android:layout_alignParentStart="true"
22
- android:layout_alignParentTop="true"
23
- android:layout_alignParentEnd="true"
24
- android:layout_alignParentBottom="true"
25
- android:background="@android:color/transparent"
26
- android:visibility="gone" />
27
-
28
- </RelativeLayout>
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 33
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 33
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 33
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 33
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.19",
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",