fbpx
Get In Touch
1201 3rd Avenue Seattle, WA 98101, US
(HQ) Av. Punto Sur 31, Tlajomulco de Zúñiga, Jal 45050, MX
Carrera 11B # 99 - 25, Btá, 110221, CO
Let's talk
hello@inmediatum.com
Ph: +1 (650) 603 0883
Sales attention M - F 9am - 5pm (CT)
Get support
Careers
Endless inspiration and meaningful work
See open positions
Back

Cámara personalizada en Android – Primeros pasos

¡Qué tal! Eduardo Rodríguez de este lado del monitor para hablarles un poco acerca de como crear una cámara personalizada en Android, pero antes no olvides pasarte por mi articulo anterior en el cual explico como crear una red VPN en 15 min.

Un poco de contexto

Como todos sabemos la cámara es una de los elementos mas importantes de nuestros dispositivos Android. Siempre buscamos que tome las mejores fotos, que su angular sea el mejor, que funcione bien en condiciones de poca luz, etc. Y el punto de esto es muy simple, nos encanta la fotografía y es por eso que los fabricantes se esfuerzan (algunos mas que otros debemos admitir) versión a versión en mejorar el software y hardware relacionados con este aspecto, pero ¿que pasa cuando nosotros como desarrolladores necesitamos tener acceso a dicha característica?.

Vamos entrando en materia

Cuando nosotros como desarrolladores necesitamos uso de la cámara generalmente es algo muy sencillo, ya que en realidad es solo pedirle permisos al usuario para usarla y mandar llamarla, lo cual nos mostrará la interfaz y características (en la mayoría de los casos) que el fabricante de nuestro equipo ha creado para tal tarea. Sencillo, ¿cierto?.

¿Y eso es suficiente?

Algo que siempre debemos considerar es que no todas las soluciones aplican para todos los problemas. Para muchos desarrolladores, dependiendo del proyecto y las necesidades de este la solución ya mencionada vendrá perfecto y podrán hacer uso de la cámara sin ir mas allá. ¿Pero que pasa cuando necesitamos mas control sobre ella? ¿Que tal si queremos una cámara con menos botones en su interfaz, o una que empiece a grabar automáticamente después de mostrar un contador?

Cámara personalizada

Básicamente Android nos provee de un conjunto de funciones para poder llevar mas allá la cámara del dispositivo con el que estamos trabajando, si bien el fabricante definió la interfaz, características y parámetros a las que el usuario tiene acceso, nosotros como programadores somos capaces de crear nuestra propia interfaz con nuestros propios parámetros y usarlos dentro de nuestra aplicación, abriendo esto un abanico inmenso de posibilidades.

Veamos un poco de código de nuestra cámara personalizada

Empecemos por el layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SurfaceView
        android:id="@+id/surfaceCameraPreview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <RelativeLayout
        android:id="@+id/overlay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/primary_black">

        <ImageView
            android:id="@+id/changeCameraBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_change_camera"
            android:layout_centerInParent="true"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="20dp"/>

    </RelativeLayout>

</RelativeLayout>

Como podras ver, el layout no tiene nada de complejo. El componente clave aqui es el SurfaceView, que la parte donde se verá el preview de nuestra cámara personalizada.

Ahora veamos el código

mCameraSource = CameraSource.Builder(context)
    .setFacing(CameraSource.CAMERA_FACING_BACK)
    .setRequestedPreviewSize(1280, 1024)
    .setAutoFocusEnabled(true)
    .build()

surfaceCameraPreview.holder.addCallback(object : SurfaceHolder.Callback {
    override fun surfaceChanged(p0: SurfaceHolder?, p1: Int, p2: Int, p3: Int) {
    }

    override fun surfaceDestroyed(p0: SurfaceHolder?) {
        mCameraSource?.stop()
    }

    @SuppressLint("MissingPermission")
    override fun surfaceCreated(p0: SurfaceHolder?) {
        try {
            mCameraSource?.start(surfaceCameraPreview.holder)
            // Get the preview size
            val previewWidth = surfaceCameraPreview.getMeasuredWidth()
            val previewHeight = surfaceCameraPreview.getMeasuredHeight()

            val overlayParams = overlay.layoutParams as RelativeLayout.LayoutParams
            overlayParams.height = previewHeight - previewWidth
            overlay.layoutParams = overlayParams

        } catch (e: Exception) {
            Utils.toast("Error:  ${e.message}")
        }
    }
})

Como podrás observa, lo único que esta pasando en esta parte de código es que se esta creando una instancia de CameraSource y se esta iniciando cuando nuestro componente SurfaceView esta listo. Lo que esta pasando después de inicializar la instancia de CameraSource es lo que hara que nuestro layout overlay ajuste su alto para que nuestro preview siempre sea un cuadrado.

Thread{
    mCameraSource?.takePicture(null, CameraSource.PictureCallback { data ->

        var bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)

        val orientation = Exif.getOrientation(data)

        when (orientation) {
            90 -> {
                bitmap = bitmap.rotate(90F)

            }
            180 -> {
                bitmap = bitmap.rotate(180F)

            }
            270-> {
                bitmap = bitmap.rotate(270F)

            }
        }

        val squareImage = Bitmap.createBitmap(
                bitmap,
                0,
                0,
                bitmap.width,
                bitmap.width
        )
    })
}.start()

Lo único que nos queda por hacer es tomar la foto, y básicamente este es el código que se usa para dicha acción. Lo que esta pasando en este fragmento de código es que se esta sacando un bitmap del preview que tenemos, después se esta validando la orientación para que la imagen se muestre como debe ser y al final se genera un nuevo bitmap totalmente cuadrado, que es el objetivo de nuestra cámara personalizada.

Conclusion

Como podrás ver esto es solo la punta del iceberg y esto abre un sin fin de cosas que se pueden realizar cuando creas tu cámara personalizada. Te invito a que lo intentes y trates de sacarle el mejor partido a todas estas herramientas que Android tiene para ti.

Espero este post te haya ayudado.

Hasta la próxima.

Eduardo Rodriguez
Eduardo Rodriguez

We use cookies to give you the best experience. Cookie Policy