react-native-unified-player 0.3.5 → 0.3.6
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.
|
@@ -169,4 +169,30 @@ class UnifiedPlayerModule(private val reactContext: ReactApplicationContext) : R
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
@ReactMethod
|
|
173
|
+
fun capture(viewTag: Int, promise: Promise) {
|
|
174
|
+
Log.d(TAG, "Native capture method called with viewTag: $viewTag")
|
|
175
|
+
try {
|
|
176
|
+
val playerView = getPlayerViewByTag(viewTag)
|
|
177
|
+
if (playerView != null) {
|
|
178
|
+
UiThreadUtil.runOnUiThread {
|
|
179
|
+
try {
|
|
180
|
+
// Assuming playerView has a method called capture() that returns a String
|
|
181
|
+
val captureResult = playerView.capture()
|
|
182
|
+
Log.d(TAG, "Capture command executed successfully, result: $captureResult")
|
|
183
|
+
promise.resolve(captureResult)
|
|
184
|
+
} catch (e: Exception) {
|
|
185
|
+
Log.e(TAG, "Error during capture: ${e.message}", e)
|
|
186
|
+
promise.reject("CAPTURE_ERROR", "Error during capture: ${e.message}", e)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
Log.e(TAG, "Player view not found for tag: $viewTag")
|
|
191
|
+
promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
|
|
192
|
+
}
|
|
193
|
+
} catch (e: Exception) {
|
|
194
|
+
Log.e(TAG, "Error in capture method: ${e.message}", e)
|
|
195
|
+
promise.reject("CAPTURE_ERROR", "Error in capture method: ${e.message}", e)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -2,11 +2,17 @@ package com.unifiedplayer
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
|
+
import android.graphics.Bitmap
|
|
6
|
+
import android.graphics.Canvas
|
|
5
7
|
import android.graphics.Color
|
|
8
|
+
import android.view.PixelCopy
|
|
9
|
+
import android.util.Base64
|
|
10
|
+
import java.io.ByteArrayOutputStream
|
|
6
11
|
import android.util.Log
|
|
7
12
|
import android.os.Handler
|
|
8
13
|
import android.os.Looper
|
|
9
14
|
import android.view.Gravity
|
|
15
|
+
import android.view.View
|
|
10
16
|
import android.widget.FrameLayout
|
|
11
17
|
import com.facebook.react.bridge.Arguments
|
|
12
18
|
import com.google.android.exoplayer2.ExoPlayer
|
|
@@ -38,6 +44,7 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
38
44
|
private var autoplay: Boolean = true
|
|
39
45
|
private var loop: Boolean = false
|
|
40
46
|
private var playerView: PlayerView
|
|
47
|
+
private var textureView: android.view.TextureView? = null
|
|
41
48
|
private var player: ExoPlayer? = null
|
|
42
49
|
private var currentProgress = 0
|
|
43
50
|
private var isPaused = false
|
|
@@ -76,17 +83,30 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
76
83
|
// Create ExoPlayer
|
|
77
84
|
player = ExoPlayer.Builder(context).build()
|
|
78
85
|
|
|
79
|
-
// Create
|
|
86
|
+
// Create TextureView for video rendering
|
|
87
|
+
textureView = android.view.TextureView(context).apply {
|
|
88
|
+
layoutParams = LayoutParams(
|
|
89
|
+
LayoutParams.MATCH_PARENT,
|
|
90
|
+
LayoutParams.MATCH_PARENT
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Create PlayerView without SurfaceView
|
|
80
95
|
playerView = PlayerView(context).apply {
|
|
81
96
|
layoutParams = LayoutParams(
|
|
82
97
|
LayoutParams.MATCH_PARENT,
|
|
83
98
|
LayoutParams.MATCH_PARENT
|
|
84
99
|
)
|
|
85
100
|
setPlayer(player)
|
|
86
|
-
|
|
101
|
+
useController = false // Disable default controls
|
|
87
102
|
}
|
|
88
103
|
|
|
104
|
+
// Add views to hierarchy
|
|
105
|
+
addView(textureView)
|
|
89
106
|
addView(playerView)
|
|
107
|
+
|
|
108
|
+
// Set TextureView as video surface
|
|
109
|
+
player?.setVideoTextureView(textureView)
|
|
90
110
|
// Add logging for playerView dimensions and post play call
|
|
91
111
|
playerView.post {
|
|
92
112
|
Log.d(TAG, "PlayerView dimensions after addView: width=${playerView.width}, height=${playerView.height}")
|
|
@@ -387,4 +407,42 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
387
407
|
progressHandler.removeCallbacks(progressRunnable) // Stop progress updates
|
|
388
408
|
player?.release()
|
|
389
409
|
}
|
|
390
|
-
|
|
410
|
+
|
|
411
|
+
fun capture(): String {
|
|
412
|
+
Log.d(TAG, "Capture method called")
|
|
413
|
+
return try {
|
|
414
|
+
player?.let { exoPlayer ->
|
|
415
|
+
// Get the video size from the player
|
|
416
|
+
val videoSize = exoPlayer.videoSize
|
|
417
|
+
if (videoSize.width <= 0 || videoSize.height <= 0) {
|
|
418
|
+
Log.e(TAG, "Invalid video dimensions: ${videoSize.width}x${videoSize.height}")
|
|
419
|
+
return ""
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Get bitmap directly from TextureView
|
|
423
|
+
val bitmap = textureView?.bitmap ?: run {
|
|
424
|
+
Log.e(TAG, "Failed to get bitmap from TextureView")
|
|
425
|
+
return ""
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Compress and encode the bitmap
|
|
429
|
+
val byteArrayOutputStream = ByteArrayOutputStream()
|
|
430
|
+
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)) {
|
|
431
|
+
val byteArray = byteArrayOutputStream.toByteArray()
|
|
432
|
+
val base64EncodedString = Base64.encodeToString(byteArray, Base64.DEFAULT)
|
|
433
|
+
Log.d(TAG, "Capture successful, base64 length: ${base64EncodedString.length}")
|
|
434
|
+
base64EncodedString
|
|
435
|
+
} else {
|
|
436
|
+
Log.e(TAG, "Failed to compress bitmap")
|
|
437
|
+
""
|
|
438
|
+
}
|
|
439
|
+
} ?: run {
|
|
440
|
+
Log.e(TAG, "Cannot capture: player is null")
|
|
441
|
+
""
|
|
442
|
+
}
|
|
443
|
+
} catch (e: Exception) {
|
|
444
|
+
Log.e(TAG, "Error during capture: ${e.message}", e)
|
|
445
|
+
""
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|