@@ -2,17 +2,25 @@ package com.mux.player.media3.examples
2
2
3
3
import android.content.Context
4
4
import android.os.Bundle
5
+ import android.text.Editable
6
+ import android.util.AttributeSet
5
7
import android.util.Log
8
+ import android.view.LayoutInflater
6
9
import android.view.Menu
7
10
import android.view.MenuItem
11
+ import android.view.View
12
+ import android.view.ViewGroup
8
13
import android.widget.Toast
9
14
import androidx.annotation.OptIn
10
15
import androidx.appcompat.app.AppCompatActivity
16
+ import androidx.constraintlayout.widget.ConstraintLayout
11
17
import androidx.media3.common.MediaItem
12
18
import androidx.media3.common.MediaMetadata
13
19
import androidx.media3.common.PlaybackException
14
20
import androidx.media3.common.Player
15
21
import androidx.media3.common.util.UnstableApi
22
+ import androidx.recyclerview.widget.RecyclerView
23
+ import androidx.recyclerview.widget.RecyclerView.ViewHolder
16
24
import com.mux.stats.sdk.core.model.CustomData
17
25
import com.mux.stats.sdk.core.model.CustomerData
18
26
import com.mux.stats.sdk.core.model.CustomerVideoData
@@ -21,6 +29,8 @@ import com.mux.stats.sdk.core.util.UUID
21
29
import com.mux.player.MuxPlayer
22
30
import com.mux.player.media3.R
23
31
import com.mux.player.media3.databinding.ActivityConfigurablePlayerBinding
32
+ import com.mux.player.media3.databinding.NumericParamEntryBinding
33
+ import com.mux.player.media3.databinding.TextParamEntryBinding
24
34
25
35
/* *
26
36
* A configurable example that uses the normal media3 player UI to play a video in the foreground from
@@ -46,40 +56,31 @@ class ConfigurablePlayerActivity : AppCompatActivity() {
46
56
playbackParamsHelper.restoreInstanceState(savedInstanceState)
47
57
}
48
58
49
- binding.configurablePlayerPlaybackIdIn.hint = playbackParamsHelper.playbackIdOrDefault()
59
+ binding.configurablePlayerPlaybackId.hint = playbackParamsHelper.playbackIdOrDefault()
60
+ binding.configurablePlayerPlaybackId.onClear = { playbackParamsHelper.playbackId = null }
61
+ binding.configurablePlayerCustomDomain.onClear = { playbackParamsHelper.customDomain = null }
62
+ binding.configurablePlayerInstantclipStart.onClear =
63
+ { playbackParamsHelper.assetStartTime = null }
64
+ binding.configurablePlayerInstantclipEnd.onClear = { playbackParamsHelper.assetEndTime = null }
65
+ binding.configurablePlayerPlaybackToken.onClear = { playbackParamsHelper.playbackToken = null }
66
+ binding.configurablePlayerDrmToken.onClear = { playbackParamsHelper.drmToken = null }
50
67
51
68
binding.configurablePlayerUpdateMediaItem.setOnClickListener {
52
- playbackParamsHelper.playbackId = binding.configurablePlayerPlaybackIdIn.text?.trim()?.toString()
53
- playbackParamsHelper.playbackToken =
54
- binding.configurablePlayerPlaybackTokenIn.text?.trim()?.toString()
55
- playbackParamsHelper.drmToken = binding.configurablePlayerDrmTokenIn.text?.trim()?.toString()
56
- playbackParamsHelper.customDomain = binding.configurablePlayerDomainIn.text?.trim()?.toString()
69
+ playbackParamsHelper.playbackId = binding.configurablePlayerPlaybackId.entry
70
+ playbackParamsHelper.playbackToken = binding.configurablePlayerPlaybackToken.entry
71
+ playbackParamsHelper.drmToken = binding.configurablePlayerDrmToken.entry
72
+ playbackParamsHelper.customDomain = binding.configurablePlayerCustomDomain.entry
73
+ playbackParamsHelper.assetStartTime = binding.configurablePlayerInstantclipStart.entry
74
+ playbackParamsHelper.assetEndTime = binding.configurablePlayerInstantclipEnd.entry
57
75
58
76
maybePlayMediaItem(playbackParamsHelper.createMediaItem())
59
77
}
60
- binding.configurablePlaybackIdClear.setOnClickListener {
61
- binding.configurablePlayerPlaybackIdIn.text = null
62
- playbackParamsHelper.playbackId = null
63
- }
64
- binding.configurablePlayerDrmTokenClear.setOnClickListener {
65
- binding.configurablePlayerDrmTokenIn.text = null
66
- playbackParamsHelper.drmToken = null
67
- }
68
- binding.configurablePlayerPlaybackTokenClear.setOnClickListener {
69
- binding.configurablePlayerPlaybackTokenIn.text = null
70
- playbackParamsHelper.playbackToken = null
71
- }
72
- binding.configurablePlayerDomainClear.setOnClickListener {
73
- binding.configurablePlayerDomainIn.text = null
74
- playbackParamsHelper.customDomain = null
75
- }
76
78
}
77
79
78
80
override fun onStart () {
79
81
super .onStart()
80
82
81
83
val mediaItem = playbackParamsHelper.createMediaItem()
82
-
83
84
maybePlayMediaItem(mediaItem)
84
85
}
85
86
@@ -168,7 +169,6 @@ class ConfigurablePlayerActivity : AppCompatActivity() {
168
169
169
170
out .addListener(object : Player .Listener {
170
171
override fun onPlayerError (error : PlaybackException ) {
171
- // todo - better error info than this, inline in ui
172
172
Log .e(TAG , " player error!" , error)
173
173
Toast .makeText(
174
174
this @ConfigurablePlayerActivity,
@@ -185,3 +185,109 @@ class ConfigurablePlayerActivity : AppCompatActivity() {
185
185
val TAG = ConfigurablePlayerActivity ::class .simpleName
186
186
}
187
187
}
188
+
189
+ class TextParamEntryView @JvmOverloads constructor(
190
+ context : Context ,
191
+ attrs : AttributeSet ? = null ,
192
+ defStyleAttr : Int = 0
193
+ ) : ConstraintLayout(context, attrs, defStyleAttr) {
194
+
195
+ private val binding: TextParamEntryBinding = TextParamEntryBinding .inflate(
196
+ LayoutInflater .from(context),
197
+ this ,
198
+ true
199
+ )
200
+
201
+ init {
202
+ context.theme.obtainStyledAttributes(attrs, R .styleable.TextParamEntryView , 0 , R .style.Theme_MuxVideoMedia3 ).apply {
203
+ try {
204
+ hint = getString(R .styleable.TextParamEntryView_hint )
205
+ } finally {
206
+ recycle()
207
+ }
208
+ }
209
+ context.theme.obtainStyledAttributes(attrs, R .styleable.ParamEntry , 0 , 0 ).apply {
210
+ try {
211
+ title = getString(R .styleable.ParamEntry_title )
212
+ } finally {
213
+ recycle()
214
+ }
215
+ }
216
+ binding.textParamEntryClear.setOnClickListener {
217
+ binding.textParamEntryIn.text = null
218
+ onClear?.invoke()
219
+ }
220
+ }
221
+
222
+ var title: CharSequence? = null
223
+ set(value) {
224
+ binding.textParamEntryLbl.text = value
225
+ field = value
226
+ }
227
+ var hint: CharSequence? = null
228
+ set(value) {
229
+ binding.textParamEntryIn.hint = value
230
+ field = value
231
+ }
232
+
233
+ var onClear: (() -> Unit )? = null
234
+ val entry: String? get() {
235
+ val text = binding.textParamEntryIn.text?.trim()?.ifEmpty { null }?.toString()
236
+ return text
237
+ }
238
+ }
239
+
240
+ class NumericParamEntryView @JvmOverloads constructor(
241
+ context : Context ,
242
+ attrs : AttributeSet ? = null ,
243
+ defStyleAttr : Int = 0
244
+ ) : ConstraintLayout(context, attrs, defStyleAttr) {
245
+
246
+ private val binding: NumericParamEntryBinding = NumericParamEntryBinding .inflate(
247
+ LayoutInflater .from(context),
248
+ this ,
249
+ true
250
+ )
251
+
252
+ init {
253
+ context.theme.obtainStyledAttributes(attrs, R .styleable.NumericParamEntryView , 0 , 0 ).apply {
254
+ try {
255
+ hint = getFloat(R .styleable.NumericParamEntryView_hint_num , Float .NaN )
256
+ .toDouble()
257
+ .takeIf { ! it.isNaN() }
258
+ } finally {
259
+ recycle()
260
+ }
261
+ }
262
+ context.theme.obtainStyledAttributes(attrs, R .styleable.ParamEntry , 0 , 0 ).apply {
263
+ try {
264
+ title = getString(R .styleable.ParamEntry_title )
265
+ } finally {
266
+ recycle()
267
+ }
268
+ }
269
+
270
+ binding.numericParamEntryClear.setOnClickListener {
271
+ binding.numericParamEntryIn.text = null
272
+ onClear?.invoke()
273
+ }
274
+ }
275
+
276
+ var title: CharSequence? = null
277
+ set(value) {
278
+ binding.numericParamEntryLbl.text = value
279
+ field = value
280
+ }
281
+ var hint: Double? = null
282
+ set(value) {
283
+ binding.numericParamEntryIn.hint = value?.toString()
284
+ field = value
285
+ }
286
+
287
+ var onClear: (() -> Unit )? = null
288
+ val entry: Double? get() {
289
+ val text =
290
+ binding.numericParamEntryIn.text?.trim()?.ifEmpty { null }?.toString()?.toDoubleOrNull()
291
+ return text
292
+ }
293
+ }
0 commit comments