react-native-unified-player 0.3.6 → 0.3.7
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/android/build.gradle
CHANGED
|
@@ -77,6 +77,6 @@ dependencies {
|
|
|
77
77
|
implementation "com.facebook.react:react-android"
|
|
78
78
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
implementation "com.google.android.exoplayer:exoplayer-core:2.19.0"
|
|
81
|
+
implementation "com.google.android.exoplayer:exoplayer-ui:2.19.0"
|
|
82
82
|
}
|
|
@@ -43,9 +43,8 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
43
43
|
private var videoUrl: String? = null
|
|
44
44
|
private var autoplay: Boolean = true
|
|
45
45
|
private var loop: Boolean = false
|
|
46
|
-
private var
|
|
47
|
-
|
|
48
|
-
private var player: ExoPlayer? = null
|
|
46
|
+
private var textureView: android.view.TextureView
|
|
47
|
+
internal var player: ExoPlayer? = null
|
|
49
48
|
private var currentProgress = 0
|
|
50
49
|
private var isPaused = false
|
|
51
50
|
|
|
@@ -83,33 +82,23 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
83
82
|
// Create ExoPlayer
|
|
84
83
|
player = ExoPlayer.Builder(context).build()
|
|
85
84
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// Create PlayerView without SurfaceView
|
|
95
|
-
playerView = PlayerView(context).apply {
|
|
96
|
-
layoutParams = LayoutParams(
|
|
97
|
-
LayoutParams.MATCH_PARENT,
|
|
98
|
-
LayoutParams.MATCH_PARENT
|
|
99
|
-
)
|
|
100
|
-
setPlayer(player)
|
|
101
|
-
useController = false // Disable default controls
|
|
102
|
-
}
|
|
85
|
+
// Create TextureView for video rendering
|
|
86
|
+
textureView = android.view.TextureView(context).apply {
|
|
87
|
+
layoutParams = LayoutParams(
|
|
88
|
+
LayoutParams.MATCH_PARENT,
|
|
89
|
+
LayoutParams.MATCH_PARENT
|
|
90
|
+
)
|
|
91
|
+
}
|
|
103
92
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
addView(playerView)
|
|
93
|
+
// Add TextureView to the view hierarchy
|
|
94
|
+
addView(textureView)
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
96
|
+
// We'll set the video surface when the TextureView's surface is available
|
|
97
|
+
// in the onSurfaceTextureAvailable callback
|
|
98
|
+
Log.d(TAG, "TextureView added to view hierarchy")
|
|
99
|
+
// Log dimensions of the view
|
|
100
|
+
post {
|
|
101
|
+
Log.d(TAG, "UnifiedPlayerView dimensions after init: width=${width}, height=${height}")
|
|
113
102
|
}
|
|
114
103
|
|
|
115
104
|
player?.addListener(object : Player.Listener {
|
|
@@ -195,24 +184,7 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
195
184
|
}
|
|
196
185
|
|
|
197
186
|
override fun onVideoSizeChanged(videoSize: VideoSize) {
|
|
198
|
-
//
|
|
199
|
-
Log.d(TAG, "ExoPlayer onVideoSizeChanged: videoSize=$videoSize")
|
|
200
|
-
Log.d(TAG, "Video size changed: width=${videoSize.width}, height=${videoSize.height}")
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
override fun onSurfaceSizeChanged(width: Int, height: Int) {
|
|
204
|
-
// Called when the size of the surface changes.
|
|
205
|
-
Log.d(TAG, "ExoPlayer onSurfaceSizeChanged: width=$width, height=$height")
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
override fun onRenderedFirstFrame() {
|
|
209
|
-
// Called when the first frame is rendered.
|
|
210
|
-
Log.d(TAG, "ExoPlayer onRenderedFirstFrame")
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
override fun onSkipSilenceEnabledChanged(skipSilenceEnabled: Boolean) {
|
|
214
|
-
// Called when skip silence is enabled or disabled.
|
|
215
|
-
Log.d(TAG, "ExoPlayer onSkipSilenceEnabledChanged: skipSilenceEnabled=$skipSilenceEnabled")
|
|
187
|
+
// Handle video size changes if needed
|
|
216
188
|
}
|
|
217
189
|
})
|
|
218
190
|
}
|
|
@@ -273,14 +245,9 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
273
245
|
}
|
|
274
246
|
}
|
|
275
247
|
|
|
276
|
-
fun setAuthToken(token: String?) {
|
|
277
|
-
// Removed as per request
|
|
278
|
-
Log.d(TAG, "Auth token handling removed")
|
|
279
|
-
}
|
|
280
|
-
|
|
281
248
|
fun setAutoplay(value: Boolean) {
|
|
282
249
|
autoplay = value
|
|
283
|
-
player?.playWhenReady = value
|
|
250
|
+
player?.playWhenReady = value
|
|
284
251
|
}
|
|
285
252
|
|
|
286
253
|
fun setLoop(value: Boolean) {
|
|
@@ -316,7 +283,7 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
316
283
|
it.seekTo(milliseconds)
|
|
317
284
|
|
|
318
285
|
// Force a progress update after seeking
|
|
319
|
-
|
|
286
|
+
progressRunnable.run()
|
|
320
287
|
} ?: Log.e(TAG, "Cannot seek: player is null")
|
|
321
288
|
}
|
|
322
289
|
|
|
@@ -390,14 +357,39 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
390
357
|
val width = right - left
|
|
391
358
|
val height = bottom - top
|
|
392
359
|
Log.d(TAG, "UnifiedPlayerView onLayout: width=$width, height=$height")
|
|
393
|
-
// Ensure
|
|
394
|
-
|
|
360
|
+
// Ensure textureView gets laid out properly
|
|
361
|
+
textureView.layout(0, 0, width, height)
|
|
395
362
|
}
|
|
396
363
|
|
|
397
364
|
override fun onAttachedToWindow() {
|
|
398
365
|
super.onAttachedToWindow()
|
|
399
366
|
Log.d(TAG, "UnifiedPlayerView onAttachedToWindow")
|
|
400
|
-
|
|
367
|
+
textureView.surfaceTextureListener = object : android.view.TextureView.SurfaceTextureListener {
|
|
368
|
+
override fun onSurfaceTextureAvailable(surface: android.graphics.SurfaceTexture, width: Int, height: Int) {
|
|
369
|
+
Log.d(TAG, "TextureView onSurfaceTextureAvailable: width=$width, height=$height")
|
|
370
|
+
// Create a Surface from the SurfaceTexture and set it on the player
|
|
371
|
+
val videoSurface = android.view.Surface(surface)
|
|
372
|
+
player?.setVideoSurface(videoSurface)
|
|
373
|
+
Log.d(TAG, "Set video surface from TextureView's SurfaceTexture")
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
override fun onSurfaceTextureSizeChanged(surface: android.graphics.SurfaceTexture, width: Int, height: Int) {
|
|
377
|
+
Log.d(TAG, "TextureView onSurfaceTextureSizeChanged: width=$width, height=$height")
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
override fun onSurfaceTextureDestroyed(surface: android.graphics.SurfaceTexture): Boolean {
|
|
381
|
+
Log.d(TAG, "TextureView onSurfaceTextureDestroyed")
|
|
382
|
+
// Set the player's surface to null to release it
|
|
383
|
+
player?.setVideoSurface(null)
|
|
384
|
+
Log.d(TAG, "Cleared video surface from player")
|
|
385
|
+
return true
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
override fun onSurfaceTextureUpdated(surface: android.graphics.SurfaceTexture) {
|
|
389
|
+
// This is called very frequently, so we'll comment out this log
|
|
390
|
+
// Log.d(TAG, "TextureView onSurfaceTextureUpdated")
|
|
391
|
+
}
|
|
392
|
+
}
|
|
401
393
|
startProgressUpdates() // Use the new method to start progress updates
|
|
402
394
|
}
|
|
403
395
|
|
|
@@ -420,11 +412,31 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
420
412
|
}
|
|
421
413
|
|
|
422
414
|
// Get bitmap directly from TextureView
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
415
|
+
val bitmap = textureView.bitmap ?: run {
|
|
416
|
+
Log.e(TAG, "Failed to get bitmap from TextureView")
|
|
417
|
+
return ""
|
|
418
|
+
}
|
|
427
419
|
|
|
420
|
+
// Debugging: Log the dimensions of the bitmap
|
|
421
|
+
bitmap.let {
|
|
422
|
+
Log.d(TAG, "Bitmap dimensions: width=${it.width}, height=${it.height}")
|
|
423
|
+
|
|
424
|
+
// Check if bitmap is empty (all black)
|
|
425
|
+
var hasNonBlackPixel = false
|
|
426
|
+
for (x in 0 until it.width) {
|
|
427
|
+
for (y in 0 until it.height) {
|
|
428
|
+
if (it.getPixel(x, y) != Color.BLACK) {
|
|
429
|
+
hasNonBlackPixel = true
|
|
430
|
+
break
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (hasNonBlackPixel) break
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (!hasNonBlackPixel) {
|
|
437
|
+
Log.w(TAG, "Bitmap appears to be all black")
|
|
438
|
+
}
|
|
439
|
+
}
|
|
428
440
|
// Compress and encode the bitmap
|
|
429
441
|
val byteArrayOutputStream = ByteArrayOutputStream()
|
|
430
442
|
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)) {
|
|
@@ -439,8 +451,8 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
439
451
|
} ?: run {
|
|
440
452
|
Log.e(TAG, "Cannot capture: player is null")
|
|
441
453
|
""
|
|
442
|
-
|
|
443
|
-
|
|
454
|
+
}
|
|
455
|
+
} catch (e: Exception) {
|
|
444
456
|
Log.e(TAG, "Error during capture: ${e.message}", e)
|
|
445
457
|
""
|
|
446
458
|
}
|