Add front camera preview and camera switch UI
This commit is contained in:
parent
5be04b0217
commit
9deeb40217
5 changed files with 594 additions and 21 deletions
120
add_camera_switch.ps1
Normal file
120
add_camera_switch.ps1
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
$path = 'app\src\main\kotlin\com\bodycamera\twentyfoulabs\camera\M530CameraActivity.kt'
|
||||
|
||||
$lines = Get-Content $path
|
||||
$result = New-Object System.Collections.Generic.List[string]
|
||||
|
||||
$addedVariable = $false
|
||||
$addedButtonDeclaration = $false
|
||||
$addedButtonUi = $false
|
||||
$replacedSelector = $false
|
||||
$replacedState = $false
|
||||
|
||||
foreach ($line in $lines) {
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 1. Variable para saber que camara usa el preview
|
||||
# ---------------------------------------------------------
|
||||
if (-not $addedVariable -and
|
||||
$line -match 'private var lastTouchActionMs = 0L') {
|
||||
|
||||
$result.Add($line)
|
||||
$result.Add(' private var frontPreviewUsesFrontCamera = true')
|
||||
$addedVariable = $true
|
||||
continue
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 2. Declaracion del boton
|
||||
# ---------------------------------------------------------
|
||||
if (-not $addedButtonDeclaration -and
|
||||
$line -match 'private lateinit var closeButton: Button') {
|
||||
|
||||
$result.Add($line)
|
||||
$result.Add(' private lateinit var switchCameraButton: Button')
|
||||
$addedButtonDeclaration = $true
|
||||
continue
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 3. Insertar boton antes de captureButton
|
||||
# ---------------------------------------------------------
|
||||
if (-not $addedButtonUi -and
|
||||
$line -match '^\s*captureButton = Button\(this\)\.apply') {
|
||||
|
||||
$result.Add(' switchCameraButton = Button(this).apply {')
|
||||
$result.Add(' text = "CAMBIAR"')
|
||||
$result.Add(' setTextColor(Color.WHITE)')
|
||||
$result.Add(' textSize = 12f')
|
||||
$result.Add(' setTypeface(typeface, Typeface.BOLD)')
|
||||
$result.Add(' gravity = Gravity.CENTER')
|
||||
$result.Add(' minWidth = 0')
|
||||
$result.Add(' minHeight = 0')
|
||||
$result.Add(' setPadding(dp(8), 0, dp(8), 0)')
|
||||
$result.Add(' background = circleDrawable(0xB0000000.toInt(), Color.WHITE, dp(1))')
|
||||
$result.Add(' visibility = if (mode == MODE_FRONT_PREVIEW) View.VISIBLE else View.GONE')
|
||||
$result.Add(' elevation = dp(12).toFloat()')
|
||||
$result.Add('')
|
||||
$result.Add(' setOnClickListener {')
|
||||
$result.Add(' if (mode == MODE_FRONT_PREVIEW) {')
|
||||
$result.Add(' frontPreviewUsesFrontCamera = !frontPreviewUsesFrontCamera')
|
||||
$result.Add(' startCamera()')
|
||||
$result.Add(' }')
|
||||
$result.Add(' }')
|
||||
$result.Add(' }')
|
||||
$result.Add('')
|
||||
$result.Add(' root.addView(')
|
||||
$result.Add(' switchCameraButton,')
|
||||
$result.Add(' FrameLayout.LayoutParams(dp(110), dp(48), Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL).apply {')
|
||||
$result.Add(' bottomMargin = dp(76)')
|
||||
$result.Add(' }')
|
||||
$result.Add(' )')
|
||||
$result.Add('')
|
||||
|
||||
$result.Add($line)
|
||||
$addedButtonUi = $true
|
||||
continue
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 4. Selector dinamico frontal/posterior SOLO para preview
|
||||
# ---------------------------------------------------------
|
||||
if (-not $replacedSelector -and
|
||||
$line -match 'CameraSelector\.DEFAULT_FRONT_CAMERA') {
|
||||
|
||||
$result.Add(' if (frontPreviewUsesFrontCamera)')
|
||||
$result.Add(' CameraSelector.DEFAULT_FRONT_CAMERA')
|
||||
$result.Add(' else')
|
||||
$result.Add(' CameraSelector.DEFAULT_BACK_CAMERA,')
|
||||
$replacedSelector = $true
|
||||
continue
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 5. Cambiar mensaje segun camara
|
||||
# ---------------------------------------------------------
|
||||
if (-not $replacedState -and
|
||||
$line -match 'stateText\.text = "Camara frontal lista"') {
|
||||
|
||||
$result.Add(' stateText.text = if (frontPreviewUsesFrontCamera)')
|
||||
$result.Add(' "Camara frontal lista"')
|
||||
$result.Add(' else')
|
||||
$result.Add(' "Camara posterior lista"')
|
||||
$replacedState = $true
|
||||
continue
|
||||
}
|
||||
|
||||
$result.Add($line)
|
||||
}
|
||||
|
||||
Set-Content -Path $path -Value $result -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=========================================="
|
||||
Write-Host "CAMBIO DE CAMARA AGREGADO"
|
||||
Write-Host "=========================================="
|
||||
Write-Host "Variable: $addedVariable"
|
||||
Write-Host "Declaracion boton: $addedButtonDeclaration"
|
||||
Write-Host "UI boton: $addedButtonUi"
|
||||
Write-Host "Selector: $replacedSelector"
|
||||
Write-Host "Estado: $replacedState"
|
||||
Write-Host ""
|
||||
|
|
@ -57,6 +57,7 @@ class MainActivity : ComponentActivity() {
|
|||
@Inject lateinit var authSessionStore: AuthSessionStore
|
||||
|
||||
@Volatile private var isAuthenticated = false
|
||||
private var frontPreviewOpened = false
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
|
|
@ -97,7 +98,16 @@ class MainActivity : ComponentActivity() {
|
|||
})
|
||||
|
||||
lifecycleScope.launch {
|
||||
authSessionStore.token.collect { token -> isAuthenticated = !token.isNullOrBlank() }
|
||||
authSessionStore.token.collect { token ->
|
||||
isAuthenticated = !token.isNullOrBlank()
|
||||
|
||||
if (isAuthenticated && !frontPreviewOpened) {
|
||||
frontPreviewOpened = true
|
||||
runOnUiThread {
|
||||
openFrontPreview()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerHardwareReceiver()
|
||||
|
|
@ -222,6 +232,20 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private fun openFrontPreview() {
|
||||
if (!isAuthenticated) return
|
||||
|
||||
startActivity(
|
||||
android.content.Intent(
|
||||
this,
|
||||
com.bodycamera.twentyfoulabs.camera.M530CameraActivity::class.java
|
||||
).putExtra(
|
||||
com.bodycamera.twentyfoulabs.camera.M530CameraActivity.EXTRA_MODE,
|
||||
com.bodycamera.twentyfoulabs.camera.M530CameraActivity.MODE_FRONT_PREVIEW
|
||||
).addFlags(android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
)
|
||||
}
|
||||
private fun handlePhotoButton() {
|
||||
startActivity(
|
||||
android.content.Intent(
|
||||
|
|
@ -374,3 +398,4 @@ fun AppNavigation(viewModel: MainViewModel, onOpenPhotoCamera: () -> Unit, onOpe
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package com.bodycamera.twentyfoulabs.camera
|
||||
package com.bodycamera.twentyfoulabs.camera
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentValues
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
|
|
@ -54,6 +55,7 @@ class M530CameraActivity : ComponentActivity() {
|
|||
const val EXTRA_MODE = "mode"
|
||||
const val MODE_PHOTO = "photo"
|
||||
const val MODE_VIDEO = "video"
|
||||
const val MODE_FRONT_PREVIEW = "front_preview"
|
||||
}
|
||||
|
||||
private lateinit var previewView: PreviewView
|
||||
|
|
@ -63,6 +65,7 @@ class M530CameraActivity : ComponentActivity() {
|
|||
private lateinit var physicalHintText: TextView
|
||||
private lateinit var captureButton: Button
|
||||
private lateinit var closeButton: Button
|
||||
private lateinit var switchCameraButton: Button
|
||||
private lateinit var recordDot: TextView
|
||||
private lateinit var chronometer: Chronometer
|
||||
|
||||
|
|
@ -73,10 +76,11 @@ class M530CameraActivity : ComponentActivity() {
|
|||
private var cameraProvider: ProcessCameraProvider? = null
|
||||
private var lastPhysicalActionMs = 0L
|
||||
private var lastTouchActionMs = 0L
|
||||
private var frontPreviewUsesFrontCamera = true
|
||||
|
||||
private val cameraPermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
|
||||
if (granted) startCamera() else stateText.text = "Permiso de cámara requerido"
|
||||
if (granted) startCamera() else stateText.text = "Permiso de camara requerido"
|
||||
}
|
||||
|
||||
private val audioPermissionLauncher =
|
||||
|
|
@ -140,7 +144,11 @@ class M530CameraActivity : ComponentActivity() {
|
|||
}
|
||||
|
||||
modeText = TextView(this).apply {
|
||||
text = if (mode == MODE_VIDEO) "VIDEO" else "FOTO"
|
||||
text = when (mode) {
|
||||
MODE_VIDEO -> "VIDEO"
|
||||
MODE_FRONT_PREVIEW -> "FRONTAL"
|
||||
else -> "FOTO"
|
||||
}
|
||||
setTextColor(if (mode == MODE_VIDEO) 0xFFFF3B30.toInt() else 0xFFFFC400.toInt())
|
||||
textSize = 14f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
|
|
@ -173,10 +181,11 @@ class M530CameraActivity : ComponentActivity() {
|
|||
setPadding(dp(10), dp(5), dp(10), dp(5))
|
||||
setBackgroundColor(0x7A000000)
|
||||
isClickable = false
|
||||
visibility = if (mode == MODE_FRONT_PREVIEW) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
recordDot = TextView(this).apply {
|
||||
text = "●"
|
||||
text = "*"
|
||||
setTextColor(0xFFFF3B30.toInt())
|
||||
textSize = 18f
|
||||
visibility = View.GONE
|
||||
|
|
@ -203,33 +212,89 @@ class M530CameraActivity : ComponentActivity() {
|
|||
)
|
||||
|
||||
closeButton = Button(this).apply {
|
||||
text = "×"
|
||||
text = "X"
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 25f
|
||||
textSize = 18f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
minWidth = 0
|
||||
minHeight = 0
|
||||
setPadding(0, 0, 0, 0)
|
||||
background = circleDrawable(0xB0000000.toInt(), Color.WHITE, dp(1))
|
||||
|
||||
background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.OVAL
|
||||
setColor(0x99000000.toInt())
|
||||
setStroke(dp(1), 0xCCFFFFFF.toInt())
|
||||
}
|
||||
|
||||
isClickable = true
|
||||
isFocusable = true
|
||||
elevation = dp(12).toFloat()
|
||||
elevation = dp(8).toFloat()
|
||||
contentDescription = "Cerrar"
|
||||
|
||||
setOnClickListener {
|
||||
stopRecordingIfNeeded()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
root.addView(
|
||||
closeButton,
|
||||
FrameLayout.LayoutParams(dp(54), dp(54), Gravity.TOP or Gravity.END).apply {
|
||||
topMargin = dp(62)
|
||||
FrameLayout.LayoutParams(dp(44), dp(44), Gravity.TOP or Gravity.END).apply {
|
||||
topMargin = dp(60)
|
||||
rightMargin = dp(12)
|
||||
}
|
||||
)
|
||||
|
||||
switchCameraButton = Button(this).apply {
|
||||
text = "CAMARA POSTERIOR"
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 11f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
gravity = Gravity.CENTER
|
||||
minWidth = 0
|
||||
minHeight = 0
|
||||
setPadding(dp(16), 0, dp(16), 0)
|
||||
|
||||
background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = dp(24).toFloat()
|
||||
setColor(0xB31A1A1A.toInt())
|
||||
setStroke(dp(1), 0xCCFFFFFF.toInt())
|
||||
}
|
||||
|
||||
visibility = if (mode == MODE_FRONT_PREVIEW) View.VISIBLE else View.GONE
|
||||
elevation = dp(10).toFloat()
|
||||
contentDescription = "Cambiar camara"
|
||||
|
||||
setOnClickListener {
|
||||
if (mode == MODE_FRONT_PREVIEW) {
|
||||
frontPreviewUsesFrontCamera = !frontPreviewUsesFrontCamera
|
||||
|
||||
text = if (frontPreviewUsesFrontCamera)
|
||||
"CAMARA POSTERIOR"
|
||||
else
|
||||
"CAMARA FRONTAL"
|
||||
|
||||
startCamera()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.addView(
|
||||
switchCameraButton,
|
||||
FrameLayout.LayoutParams(
|
||||
dp(170),
|
||||
dp(46),
|
||||
Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
||||
).apply {
|
||||
bottomMargin = dp(76)
|
||||
}
|
||||
)
|
||||
|
||||
captureButton = Button(this).apply {
|
||||
text = if (mode == MODE_VIDEO) "REC" else "FOTO"
|
||||
visibility = if (mode == MODE_FRONT_PREVIEW) View.GONE else View.VISIBLE
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 15f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
|
|
@ -289,14 +354,22 @@ class M530CameraActivity : ComponentActivity() {
|
|||
}
|
||||
|
||||
physicalHintText = TextView(this).apply {
|
||||
text = if (mode == MODE_VIDEO) "F5 VIDEO" else "F2 FOTO"
|
||||
text = when (mode) {
|
||||
MODE_VIDEO -> "F5 VIDEO"
|
||||
MODE_FRONT_PREVIEW -> "EN VIVO"
|
||||
else -> "F2 FOTO"
|
||||
}
|
||||
setTextColor(if (mode == MODE_VIDEO) 0xFFFF3B30.toInt() else 0xFFFFC400.toInt())
|
||||
textSize = 15f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
}
|
||||
|
||||
stateText = TextView(this).apply {
|
||||
text = if (mode == MODE_VIDEO) "Preparando video..." else "Preparando cámara..."
|
||||
text = when (mode) {
|
||||
MODE_VIDEO -> "Preparando video..."
|
||||
MODE_FRONT_PREVIEW -> "Preparando camara frontal..."
|
||||
else -> "Preparando camara..."
|
||||
}
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 13f
|
||||
gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
||||
|
|
@ -335,10 +408,10 @@ class M530CameraActivity : ComponentActivity() {
|
|||
if (now - lastTouchActionMs < 350) return
|
||||
lastTouchActionMs = now
|
||||
|
||||
if (mode == MODE_VIDEO) {
|
||||
toggleVideoRecording()
|
||||
} else {
|
||||
takePhoto()
|
||||
when (mode) {
|
||||
MODE_VIDEO -> toggleVideoRecording()
|
||||
MODE_FRONT_PREVIEW -> Unit
|
||||
else -> takePhoto()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +428,25 @@ class M530CameraActivity : ComponentActivity() {
|
|||
|
||||
provider.unbindAll()
|
||||
|
||||
if (mode == MODE_VIDEO) {
|
||||
if (mode == MODE_FRONT_PREVIEW) {
|
||||
imageCapture = null
|
||||
videoCapture = null
|
||||
|
||||
provider.bindToLifecycle(
|
||||
this,
|
||||
if (frontPreviewUsesFrontCamera)
|
||||
CameraSelector.DEFAULT_FRONT_CAMERA
|
||||
else
|
||||
CameraSelector.DEFAULT_BACK_CAMERA,
|
||||
preview
|
||||
)
|
||||
|
||||
stateText.text = if (frontPreviewUsesFrontCamera)
|
||||
"Camara frontal lista"
|
||||
else
|
||||
"Camara posterior lista"
|
||||
captureButton.isEnabled = false
|
||||
} else if (mode == MODE_VIDEO) {
|
||||
val recorder = Recorder.Builder()
|
||||
.setQualitySelector(
|
||||
QualitySelector.from(
|
||||
|
|
@ -397,7 +488,7 @@ class M530CameraActivity : ComponentActivity() {
|
|||
captureButton.isEnabled = true
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
stateText.text = "Error de cámara"
|
||||
stateText.text = "Error de camara"
|
||||
captureButton.isEnabled = false
|
||||
}
|
||||
}, ContextCompat.getMainExecutor(this))
|
||||
|
|
@ -405,7 +496,7 @@ class M530CameraActivity : ComponentActivity() {
|
|||
|
||||
private fun takePhoto() {
|
||||
val capture = imageCapture ?: run {
|
||||
stateText.text = "Cámara no lista"
|
||||
stateText.text = "Camara no lista"
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -624,7 +715,7 @@ class M530CameraActivity : ComponentActivity() {
|
|||
chronometer.visibility = View.GONE
|
||||
recordDot.visibility = View.GONE
|
||||
|
||||
stateText.text = if (error) "Error de grabación" else "Video guardado"
|
||||
stateText.text = if (error) "Error de grabacion" else "Video guardado"
|
||||
physicalHintText.text = "F5 VIDEO"
|
||||
|
||||
captureButton.text = "REC"
|
||||
|
|
@ -641,6 +732,7 @@ class M530CameraActivity : ComponentActivity() {
|
|||
setBackgroundColor(Color.WHITE)
|
||||
alpha = 0.75f
|
||||
isClickable = false
|
||||
visibility = if (mode == MODE_FRONT_PREVIEW) View.GONE else View.VISIBLE
|
||||
}
|
||||
val root = findViewById<FrameLayout>(android.R.id.content)
|
||||
root.addView(
|
||||
|
|
@ -712,3 +804,8 @@ class M530CameraActivity : ComponentActivity() {
|
|||
private fun timestamp(): String =
|
||||
SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.US).format(Date())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
157
apply_front_preview_v2.ps1
Normal file
157
apply_front_preview_v2.ps1
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
$cameraPath = 'app\src\main\kotlin\com\bodycamera\twentyfoulabs\camera\M530CameraActivity.kt'
|
||||
$mainPath = 'app\src\main\kotlin\com\bodycamera\twentyfoulabs\MainActivity.kt'
|
||||
|
||||
$camera = Get-Content $cameraPath -Raw
|
||||
$main = Get-Content $mainPath -Raw
|
||||
|
||||
# ============================================================
|
||||
# M530CameraActivity.kt
|
||||
# ============================================================
|
||||
|
||||
# 1. Agregar modo FRONT_PREVIEW
|
||||
$camera = [regex]::Replace(
|
||||
$camera,
|
||||
'const val MODE_VIDEO = "video"',
|
||||
'const val MODE_VIDEO = "video"' + [Environment]::NewLine +
|
||||
' const val MODE_FRONT_PREVIEW = "front_preview"',
|
||||
1
|
||||
)
|
||||
|
||||
# 2. Texto superior
|
||||
$camera = $camera.Replace(
|
||||
'text = if (mode == MODE_VIDEO) "VIDEO" else "FOTO"',
|
||||
'text = when (mode) {' + [Environment]::NewLine +
|
||||
' MODE_VIDEO -> "VIDEO"' + [Environment]::NewLine +
|
||||
' MODE_FRONT_PREVIEW -> "CAMARA FRONTAL"' + [Environment]::NewLine +
|
||||
' else -> "FOTO"' + [Environment]::NewLine +
|
||||
' }'
|
||||
)
|
||||
|
||||
# 3. Ocultar botón de captura cuando sea preview frontal
|
||||
$camera = $camera.Replace(
|
||||
'text = if (mode == MODE_VIDEO) "REC" else "FOTO"',
|
||||
'text = if (mode == MODE_VIDEO) "REC" else "FOTO"' + [Environment]::NewLine +
|
||||
' visibility = if (mode == MODE_FRONT_PREVIEW) View.GONE else View.VISIBLE'
|
||||
)
|
||||
|
||||
# 4. Texto inferior
|
||||
$camera = $camera.Replace(
|
||||
'text = if (mode == MODE_VIDEO) "F5 VIDEO" else "F2 FOTO"',
|
||||
'text = when (mode) {' + [Environment]::NewLine +
|
||||
' MODE_VIDEO -> "F5 VIDEO"' + [Environment]::NewLine +
|
||||
' MODE_FRONT_PREVIEW -> "VISTA EN VIVO"' + [Environment]::NewLine +
|
||||
' else -> "F2 FOTO"' + [Environment]::NewLine +
|
||||
' }'
|
||||
)
|
||||
|
||||
# 5. Estado inicial
|
||||
$camera = [regex]::Replace(
|
||||
$camera,
|
||||
'text = if \(mode == MODE_VIDEO\) "Preparando video\.\.\." else ".*?"',
|
||||
'text = when (mode) {' + [Environment]::NewLine +
|
||||
' MODE_VIDEO -> "Preparando video..."' + [Environment]::NewLine +
|
||||
' MODE_FRONT_PREVIEW -> "Preparando camara frontal..."' + [Environment]::NewLine +
|
||||
' else -> "Preparando camara..."' + [Environment]::NewLine +
|
||||
' }',
|
||||
1
|
||||
)
|
||||
|
||||
# 6. Evitar acciones de foto/video en preview frontal
|
||||
$camera = [regex]::Replace(
|
||||
$camera,
|
||||
'if \(mode == MODE_VIDEO\) \{\s*toggleVideoRecording\(\)\s*\} else \{\s*takePhoto\(\)\s*\}',
|
||||
'when (mode) {' + [Environment]::NewLine +
|
||||
' MODE_VIDEO -> toggleVideoRecording()' + [Environment]::NewLine +
|
||||
' MODE_FRONT_PREVIEW -> Unit' + [Environment]::NewLine +
|
||||
' else -> takePhoto()' + [Environment]::NewLine +
|
||||
' }',
|
||||
1
|
||||
)
|
||||
|
||||
# 7. Usar cámara frontal solo en FRONT_PREVIEW
|
||||
$camera = [regex]::Replace(
|
||||
$camera,
|
||||
'(\s*provider\.unbindAll\(\)\s*)if \(mode == MODE_VIDEO\) \{',
|
||||
'$1if (mode == MODE_FRONT_PREVIEW) {' + [Environment]::NewLine +
|
||||
' imageCapture = null' + [Environment]::NewLine +
|
||||
' videoCapture = null' + [Environment]::NewLine +
|
||||
'' + [Environment]::NewLine +
|
||||
' provider.bindToLifecycle(' + [Environment]::NewLine +
|
||||
' this,' + [Environment]::NewLine +
|
||||
' CameraSelector.DEFAULT_FRONT_CAMERA,' + [Environment]::NewLine +
|
||||
' preview' + [Environment]::NewLine +
|
||||
' )' + [Environment]::NewLine +
|
||||
'' + [Environment]::NewLine +
|
||||
' stateText.text = "Camara frontal lista"' + [Environment]::NewLine +
|
||||
' captureButton.isEnabled = false' + [Environment]::NewLine +
|
||||
' } else if (mode == MODE_VIDEO) {',
|
||||
1
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# MainActivity.kt
|
||||
# ============================================================
|
||||
|
||||
# 8. Variable para abrir la cámara frontal una sola vez por inicio
|
||||
$main = $main.Replace(
|
||||
'@Volatile private var isAuthenticated = false',
|
||||
'@Volatile private var isAuthenticated = false' + [Environment]::NewLine +
|
||||
' private var frontPreviewOpened = false'
|
||||
)
|
||||
|
||||
# 9. Al detectar sesión válida, abrir preview frontal
|
||||
$main = [regex]::Replace(
|
||||
$main,
|
||||
'authSessionStore\.token\.collect \{ token -> isAuthenticated = !token\.isNullOrBlank\(\) \}',
|
||||
'authSessionStore.token.collect { token ->' + [Environment]::NewLine +
|
||||
' isAuthenticated = !token.isNullOrBlank()' + [Environment]::NewLine +
|
||||
'' + [Environment]::NewLine +
|
||||
' if (isAuthenticated && !frontPreviewOpened) {' + [Environment]::NewLine +
|
||||
' frontPreviewOpened = true' + [Environment]::NewLine +
|
||||
' runOnUiThread {' + [Environment]::NewLine +
|
||||
' openFrontPreview()' + [Environment]::NewLine +
|
||||
' }' + [Environment]::NewLine +
|
||||
' }' + [Environment]::NewLine +
|
||||
' }',
|
||||
1
|
||||
)
|
||||
|
||||
# 10. Función para abrir la cámara frontal
|
||||
$frontFunction = @'
|
||||
|
||||
private fun openFrontPreview() {
|
||||
if (!isAuthenticated) return
|
||||
|
||||
startActivity(
|
||||
android.content.Intent(
|
||||
this,
|
||||
com.bodycamera.twentyfoulabs.camera.M530CameraActivity::class.java
|
||||
).putExtra(
|
||||
com.bodycamera.twentyfoulabs.camera.M530CameraActivity.EXTRA_MODE,
|
||||
com.bodycamera.twentyfoulabs.camera.M530CameraActivity.MODE_FRONT_PREVIEW
|
||||
).addFlags(android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
)
|
||||
}
|
||||
|
||||
'@
|
||||
|
||||
$main = $main.Replace(
|
||||
' private fun handlePhotoButton() {',
|
||||
$frontFunction + ' private fun handlePhotoButton() {'
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# Guardar cambios
|
||||
# ============================================================
|
||||
|
||||
Set-Content -Path $cameraPath -Value $camera -Encoding UTF8
|
||||
Set-Content -Path $mainPath -Value $main -Encoding UTF8
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '=========================================='
|
||||
Write-Host 'FRONT PREVIEW V2 APLICADO'
|
||||
Write-Host '=========================================='
|
||||
Write-Host 'MODE_FRONT_PREVIEW agregado'
|
||||
Write-Host 'Camara frontal configurada'
|
||||
Write-Host 'F2 y F5 mantienen camara trasera'
|
||||
Write-Host ''
|
||||
174
improve_camera_buttons_ui.ps1
Normal file
174
improve_camera_buttons_ui.ps1
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
$path = 'app\src\main\kotlin\com\bodycamera\twentyfoulabs\camera\M530CameraActivity.kt'
|
||||
|
||||
$c = Get-Content $path -Raw
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Import para fondos redondeados
|
||||
# ---------------------------------------------------------
|
||||
if ($c -notmatch 'import android\.graphics\.drawable\.GradientDrawable') {
|
||||
$c = $c.Replace(
|
||||
'import android.graphics.Typeface',
|
||||
"import android.graphics.Typeface`r`nimport android.graphics.drawable.GradientDrawable"
|
||||
)
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Boton CERRAR
|
||||
# ---------------------------------------------------------
|
||||
$oldClose = @'
|
||||
closeButton = Button(this).apply {
|
||||
text = "X"
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 25f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
minWidth = 0
|
||||
minHeight = 0
|
||||
setPadding(0, 0, 0, 0)
|
||||
background = circleDrawable(0xB0000000.toInt(), Color.WHITE, dp(1))
|
||||
isClickable = true
|
||||
isFocusable = true
|
||||
elevation = dp(12).toFloat()
|
||||
setOnClickListener {
|
||||
stopRecordingIfNeeded()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
root.addView(
|
||||
closeButton,
|
||||
FrameLayout.LayoutParams(dp(54), dp(54), Gravity.TOP or Gravity.END).apply {
|
||||
topMargin = dp(62)
|
||||
rightMargin = dp(12)
|
||||
}
|
||||
)
|
||||
'@
|
||||
|
||||
$newClose = @'
|
||||
closeButton = Button(this).apply {
|
||||
text = "X"
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 18f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
minWidth = 0
|
||||
minHeight = 0
|
||||
setPadding(0, 0, 0, 0)
|
||||
|
||||
background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.OVAL
|
||||
setColor(0x99000000.toInt())
|
||||
setStroke(dp(1), 0xCCFFFFFF.toInt())
|
||||
}
|
||||
|
||||
isClickable = true
|
||||
isFocusable = true
|
||||
elevation = dp(8).toFloat()
|
||||
contentDescription = "Cerrar"
|
||||
|
||||
setOnClickListener {
|
||||
stopRecordingIfNeeded()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
root.addView(
|
||||
closeButton,
|
||||
FrameLayout.LayoutParams(dp(44), dp(44), Gravity.TOP or Gravity.END).apply {
|
||||
topMargin = dp(60)
|
||||
rightMargin = dp(12)
|
||||
}
|
||||
)
|
||||
'@
|
||||
|
||||
$c = $c.Replace($oldClose, $newClose)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Boton CAMBIAR CAMARA
|
||||
# ---------------------------------------------------------
|
||||
$oldSwitch = @'
|
||||
switchCameraButton = Button(this).apply {
|
||||
text = "CAMBIAR"
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 12f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
gravity = Gravity.CENTER
|
||||
minWidth = 0
|
||||
minHeight = 0
|
||||
setPadding(dp(8), 0, dp(8), 0)
|
||||
background = circleDrawable(0xB0000000.toInt(), Color.WHITE, dp(1))
|
||||
visibility = if (mode == MODE_FRONT_PREVIEW) View.VISIBLE else View.GONE
|
||||
elevation = dp(12).toFloat()
|
||||
|
||||
setOnClickListener {
|
||||
if (mode == MODE_FRONT_PREVIEW) {
|
||||
frontPreviewUsesFrontCamera = !frontPreviewUsesFrontCamera
|
||||
startCamera()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.addView(
|
||||
switchCameraButton,
|
||||
FrameLayout.LayoutParams(dp(110), dp(48), Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL).apply {
|
||||
bottomMargin = dp(76)
|
||||
}
|
||||
)
|
||||
'@
|
||||
|
||||
$newSwitch = @'
|
||||
switchCameraButton = Button(this).apply {
|
||||
text = "CAMARA POSTERIOR"
|
||||
setTextColor(Color.WHITE)
|
||||
textSize = 11f
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
gravity = Gravity.CENTER
|
||||
minWidth = 0
|
||||
minHeight = 0
|
||||
setPadding(dp(16), 0, dp(16), 0)
|
||||
|
||||
background = GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = dp(24).toFloat()
|
||||
setColor(0xB31A1A1A.toInt())
|
||||
setStroke(dp(1), 0xCCFFFFFF.toInt())
|
||||
}
|
||||
|
||||
visibility = if (mode == MODE_FRONT_PREVIEW) View.VISIBLE else View.GONE
|
||||
elevation = dp(10).toFloat()
|
||||
contentDescription = "Cambiar camara"
|
||||
|
||||
setOnClickListener {
|
||||
if (mode == MODE_FRONT_PREVIEW) {
|
||||
frontPreviewUsesFrontCamera = !frontPreviewUsesFrontCamera
|
||||
|
||||
text = if (frontPreviewUsesFrontCamera)
|
||||
"CAMARA POSTERIOR"
|
||||
else
|
||||
"CAMARA FRONTAL"
|
||||
|
||||
startCamera()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.addView(
|
||||
switchCameraButton,
|
||||
FrameLayout.LayoutParams(
|
||||
dp(170),
|
||||
dp(46),
|
||||
Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
||||
).apply {
|
||||
bottomMargin = dp(76)
|
||||
}
|
||||
)
|
||||
'@
|
||||
|
||||
$c = $c.Replace($oldSwitch, $newSwitch)
|
||||
|
||||
Set-Content -Path $path -Value $c -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=========================================="
|
||||
Write-Host "UI DE CAMARA ACTUALIZADA"
|
||||
Write-Host "=========================================="
|
||||
Write-Host ""
|
||||
Loading…
Add table
Add a link
Reference in a new issue