¿Cómo construir un backend para una aplicación de Android?

Back4app Android App Cover

En este artículo, hablaremos sobre Android, uno de los sistemas operativos más populares. Analizaremos los pros y los contras del desarrollo de Android, las opciones de backend para aplicaciones móviles y le enseñaremos cómo crear su propio backend móvil.

Aportes clave

  • Dominio de Android: Android, como sistema operativo de código abierto, alimenta aproximadamente el 70% de los dispositivos móviles con más de tres mil millones de usuarios activos.
  • Opciones de backend para aplicaciones: para los backend de aplicaciones móviles, los desarrolladores pueden optar por Infraestructura como servicio (IaaS), Plataforma como servicio (PaaS) o Backend como servicio (BaaS).
  • Pasos para construir su backend: Proporcionaremos un tutorial detallado sobre cómo hacer un backend de Android utilizando una plataforma BaaS y el código fuente al final del artículo.

¿Qué es Android?

Android es un sistema operativo gratuito y de código abierto basado en Linux. Fue diseñado principalmente para dispositivos móviles como smartphones y tablets, pero ahora también se usa para televisores inteligentes, sistemas integrados, consolas de juegos, etc.

Android Inc. comenzó el desarrollo de Android en 2003. Inicialmente, la empresa quería crear un sistema operativo para cámaras digitales, pero rápidamente cambió al desarrollo de sistemas operativos móviles para llegar a un mercado más amplio.

En 2005 la empresa fue adquirida por Google junto con sus empleados. La primera versión de Android se lanzó en 2008.

Aunque Android es de código abierto, la mayoría de los dispositivos móviles ejecutan la versión patentada de Google. Su versión viene preinstalada con software como Google Chrome, YouTube, Google TV y Gmail.

Debido a las excelentes opciones de personalización de Android, muchos fabricantes también aplican skins de Android para representar mejor a su empresa. Es por eso que OnePlus Android se ve bastante diferente a Pixel Android.

Android ha sido el sistema operativo más popular desde 2013. Lo utiliza aproximadamente el 70% de los dispositivos móviles y tiene más de tres mil millones de usuarios activos mensuales.

Además de eso, Google Play Store le brinda acceso a más de tres millones de aplicaciones móviles. Sigue leyendo para aprender a crear un backend para una aplicación de Android.

Beneficios del desarrollo de Android

Exploremos algunas de las ventajas de desarrollar para Android.

Multiplataforma

Al desarrollar para Android, puede dirigirse a una amplia gama de dispositivos. Eso incluye teléfonos móviles, dispositivos portátiles, televisores inteligentes, consolas de juegos y más. Si sabe cómo codificar una aplicación móvil, no tendrá problemas para desarrollar una aplicación de televisión inteligente o portátil.

Mercado enorme

Como se presentó anteriormente, Android tiene una mayor participación de mercado con un 70%, en comparación con iOS con un 30%. Al desarrollar aplicaciones para Android, automáticamente podrá obtener acceso a una audiencia más amplia.

Además de eso, las aplicaciones de Android son conocidas por su baja inversión y su alto retorno de la inversión. A diferencia de iOS, tampoco hay tarifas anuales de desarrollador involucradas.

Personalización

Los dispositivos Android son altamente personalizables en comparación con otros sistemas operativos. Le permiten cambiar prácticamente cualquier cosa que pueda imaginar.

Además, Android le permite integrar fácilmente su aplicación con otros servicios de terceros.

Comunidad

Android está respaldado por una comunidad masiva de desarrolladores de código abierto. Además, viene con muchas herramientas amigables para desarrolladores como Android StudioADB y Logcat que le permiten codificar aplicaciones fácilmente.

Si alguna vez se queda atascado, hay varias plataformas donde puede encontrar ayuda, incluidas GitHubStackOverflowReddit y otras comunidades centradas en Android.

Limitaciones del desarrollo de Android

Estas son algunas de las desventajas del desarrollo de Android.

Seguridad

Android es menos seguro que iOS y no sigue protocolos de seguridad estrictos. Dado que Android es de código abierto, las vulnerabilidades de seguridad se detectan semanalmente. Esto les da a los piratas informáticos la capacidad de explotar estas vulnerabilidades antes de que se parcheen.

Los dispositivos Android también se pueden rootear para obtener acceso de superusuario. Si bien hace que su dispositivo sea más poderoso, también es riesgoso ya que deshabilita algunas medidas de seguridad integradas.

Complejidad

Los dispositivos Android vienen en diferentes formas y tamaños, y aunque eso es genial, puede ser un gran inconveniente al desarrollar aplicaciones de Android para varios tipos de dispositivos.

Para asegurarse de que su aplicación sea compatible con tantos dispositivos como sea posible, deberá incorporar un diseño receptivo, pensar en el hardware de diferentes dispositivos, etc.

Aplicaciones premium

Las aplicaciones premium tienen menos éxito en Google Play Store que en App Store. No es ningún secreto que los usuarios de Android tienden a gastar menos en aplicaciones que los usuarios de iOS. Si está trabajando en una primera aplicación premium, considere a Android como su segunda opción.

Opciones de backend para aplicaciones de Android

¿Cuál es el mejor backend para una aplicación de Android? Los backend para aplicaciones móviles pueden alojarse en su propia infraestructura o implementarse en los servicios en la nube. Los modelos de computación en la nube más populares para backend móviles incluyen:

  1. Infrastructure as a Service (IaaS)
  2. Platform as a Service (PaaS)
  3. Backend as a Service (BaaS)

Cada opción cubre diferentes capas de abstracción, como se muestra en la imagen a continuación.

IaaS vs PaaS vs BaaS Abstraction Layers

Veamos cada opción en detalle para ayudarlo a seleccionar el modelo de nube más adecuado para sus aplicaciones de backend.

Infrastructure as a Service (IaaS)

La infraestructura como servicio (IaaS) es el modelo de computación en la nube menos abstracto. En este modelo, el proveedor ofrece a los usuarios recursos virtualizados, como servidores, redes, almacenamiento y sistemas operativos, a través de API de alto nivel o paneles intuitivos.

Lo mejor de IaaS es que brinda a los usuarios un control total sobre toda su infraestructura. IaaS es el modelo más flexible y escalable pero también el más difícil de gestionar. Si elige esta opción, lo más probable es que necesite un SysAdmin o dos.

Algunos ejemplos de IaaS son Amazon Web ServicesGoogle Cloud Platform y Azure.

Platform as a Service (PaaS)

Plataforma como servicio (PaaS) es un modelo de computación en la nube diseñado para ayudar a los usuarios a desarrollar, administrar e implementar aplicaciones.

Además de proporcionar infraestructura, PaaS viene con herramientas fáciles de usar para desarrollar, personalizar y probar aplicaciones.

Al utilizar PaaS, podrá concentrarse en su software y experiencia de usuario sin preocuparse por la infraestructura subyacente.

Además, PaaS garantizará que su aplicación se escale a pedido, se encargará de las copias de seguridad, etcétera. Las desventajas de PaaS son un menor nivel de control, el riesgo de bloqueo de proveedores y costos comparativamente más altos.

Las plataformas PaaS más populares incluyen Heroku, Render y Digital Ocean App Platform.

Backend as a Service (BaaS)

Backend como servicio (BaaS) automatiza la parte de backend del desarrollo al proporcionar una solución de backend completa.

Las características de BaaS incluyen administración de usuarios, bases de datos, autenticación, integraciones sociales, notificaciones automáticas, API, SDK y más.

BaaS le brinda todas las ventajas de IaaS y PaaS al tiempo que proporciona funcionalidades adicionales. Los equipos que aprovechan BaaS tienden a lanzar sus productos más rápido, reducir los costos de ingeniería y crear un mejor software.

Las desventajas de BaaS incluyen un nivel más bajo de control y personalización y la posibilidad de bloqueo de proveedores para plataformas que no son de código abierto.

Los ejemplos de BaaS incluyen Back4app, AWS Amplify y Firebase.

¿Cómo hacer un backend para una aplicación de Android?

En la sección de este artículo, veremos cómo crear una aplicación de backend basada en Back4app y conectarnos a ella desde una aplicación de Android.

Prerrequisitos

¿Qué es Back4app?

Back4app es una excelente plataforma para crear backend para aplicaciones modernas y acelerar el proceso de desarrollo.

Viene bien equipado con funciones útiles del lado del servidor, como administración de usuarios, bases de datos en tiempo real, integraciones sociales, funciones de código en la nube, notificaciones automáticas, API y más.

Al utilizar Back4app, podrá externalizar gran parte del trabajo de backend y concentrarse en los aspectos críticos de su aplicación y acelerar el desarrollo de backend de una aplicación de Android.

No habrá necesidad de lidiar con la infraestructura subyacente de su backend, el servidor backend, el escalado, el mantenimiento, etcétera.

Lo más importante es que Back4app ofrece un nivel gratuito que es excelente para experimentar y probar la plataforma. A medida que crece su aplicación, puede actualizar a planes premium con una tarifa mensual.

Introducción al proyecto

En este artículo, crearemos una aplicación de notas simple. La aplicación permitirá a los usuarios agregar, editar y eliminar notas. Las notas se almacenarán en la base de datos de Back4app y se manipularán a través del SDK de Parse.

Usaremos el lenguaje de programación Kotlin para construir la aplicación. Para la interfaz de usuario, utilizaremos Jetpack Compose, el conjunto de herramientas moderno de Android para crear interfaces de usuario nativas.

Back4app Android Notes App

Crear aplicación Back4app

Como primer paso para desarrollar un backend para una aplicación de Android, necesitará una cuenta Back4app. Si no tiene una, regístrese.

Al iniciar sesión en su cuenta Back4app, será redirigido a la vista de la aplicación. Haga clic en “Crear nueva aplicación” para iniciar el proceso de creación de la aplicación.

Back4app Build New App

La plataforma Back4app ofrece dos soluciones:

  1. Backend como servicio (BaaS): solución sólida de backend
  2. Contenedores como servicio (CaaS): plataforma para administrar contenedores (especialmente aplicaciones web)

Teniendo en cuenta que estamos creando un backend para una aplicación móvil, elegiremos “Backend como servicio”.

Back4app BaaS Solution

Asigne a su aplicación un nombre agradable e informativo, seleccione “NoSQL” como base de datos y haga clic en “Crear”. Ese es un paso importante para implementar un backend para una aplicación de Android.

Back4app tardará un poco en preparar todo lo necesario para su aplicación. Eso incluye la base de datos, la gestión de usuarios, el escalado, las configuraciones, etcétera. Una vez que su aplicación esté lista, será redirigido a la vista de la base de datos de su aplicación.

Back4app Database View

Diseñar la base de datos

Para avanzar, diseñemos la base de datos. Este es un paso necesario para desarrollar un backend para una aplicación de Android.

Como estamos creando una aplicación de notas simple, solo necesitaremos una clase. Haga clic en “Crear una clase”, asígnele el nombre Note, habilite “Lectura y escritura pública” y haga clic en “Crear clase y agregar columnas”.

Back4app Create Database Class

A continuación, agregue los siguientes tres campos a la clase recién creada:

+-------------+-------------+--------------------+----------+
| Data type   | Name        | Default value      | Required |
+-------------+-------------+--------------------+----------+
| String      | icon        | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+
| String      | title       | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+
| String      | content     | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+

Por último, haga clic en el botón “Agregar fila” y complete su base de datos con algunos datos de muestra. Si no tiene ninguna idea, también puede importar este volcado de datos.

Back4app Populate Database

Genial, eso es todo para el backend.

Interfaz de código

En esta sección del artículo, iniciaremos una nueva aplicación de Android, configuraremos un ViewModel, implementaremos la interfaz de usuario, instalaremos y configuraremos el SDK de Parse y, por último, obtendremos datos de la base de datos en tiempo real de Back4app.

Proyecto inicial

Como se mencionó en la sección de requisitos previos, los siguientes pasos requerirán que tenga instalado Android Studio. Si aún no lo tiene, descárguelo.

Comience abriendo Android Studio y haciendo clic en el botón “Nuevo proyecto”.

Android Studio Index

Luego seleccione “Actividad vacía” como su plantilla de proyecto y haga clic en “Siguiente”.

Para crear su proyecto, debe proporcionar un nombre y un nombre de paquete. Le sugiero que use AndroidApp como nombre de su proyecto y nombre de dominio inverso como paquete de su proyecto.

Una vez que haya configurado todo, haga clic en “Finalizar” para crear el proyecto.

Android Studio Project Settings

Android Studio tardará aproximadamente dos minutos en preparar todo lo necesario. Eso incluye crear la estructura de archivos del proyecto, configurar Gradle, instalar dependencias, etc.

Una vez que su proyecto esté listo, use el explorador para navegar a MainActivity.kt y reemplace su contenido:

// app/src/main/java.<your_package_name>/MainActivity.kt

package <your.package.name>

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background,
                ) {
                    Text(text = "Back4app rocks!", fontSize = 18.sp)
                }
            }
        }
    }
}

Asegúrese de reemplazar siempre <your_package_name> con el nombre real de su paquete.

Por último, intente ejecutar la aplicación haciendo clic en el botón verde de reproducción o Shift + F10en su teclado. Si todo va bien, el emulador debería iniciarse y debería ver el mensaje Back4app mandaen la pantalla.

Android First App

ViewModel

Para administrar el estado global de nuestra aplicación, utilizaremos un ViewModel. Pero antes de eso, tenemos que crear una clase de datos Note con los mismos atributos que la de nuestra base de datos Back4app.

Cree una clase de datos llamada Note:

// app/src/main/java.<your_package_name>/Note.kt

package <your.package.name>

data class Note(
    var objectId: String? = null,
    var icon: String,
    var title: String,
    var content: String,
) {
    companion object {
        fun generateObjectId(): String {
            val chars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
            return (1..10).map { chars.random() }.joinToString("")
        }
    }
}
  1. Definimos el método estático generateObjectId() para generar ID de objetos similares a Parse.
  2. objectId es anulable ya que luego asumiremos que si objectId == null, el objeto aún no se ha guardado en la base de datos.

A continuación, cree una clase AppViewModel con los siguientes contenidos:

// app/src/main/java.<your_package_name>/AppViewModel.kt

package <your.package.name>

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class AppViewModel : ViewModel() {
    val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf(
        "7IggsqFAKt" to Note(
            objectId = "7IggsqFAKt",
            icon = "\uD83D\uDE80",
            title = "Deploy app",
            content = "Go ahead and deploy your backend to Back4app.",
        ),
        "eFRNm0hTat" to Note(
            objectId = "eFRNm0hTat",
            icon = "\uD83C\uDFA8",
            title = "Design website",
            content = "Design the website for the conference.",
        ),
        "uC7hTQmG5F" to Note(
            objectId = "uC7hTQmG5F",
            icon = "\uD83D\uDC42",
            title = "Attend meeting",
            content = "Attend meeting with the team to discuss the conference.",
        ),
    ))

    companion object {
        @Volatile
        private var instance: AppViewModel? = null

        fun getInstance(): AppViewModel {
            return instance ?: synchronized(this) {
                instance ?: AppViewModel().also { instance = it }
            }
        }
    }
}
  1. Utilizamos MutableState de Compose para activar actualizaciones de la interfaz de usuario en caso de cambio de datos.
  2. MutableState contiene un mapa de objectIds y Notes, que completamos con datos.
  3. Para asegurarnos de que solo haya una única instancia de AppViewModel, usamos el patrón singleton.

Ahora podemos acceder a la instancia de AppViewModel en nuestras actividades a través de AppViewModel.getInstance().

Actividad principal

Continuando, reemplace el contenido de MainActivity.kt con el siguiente código para mostrar las notas:

// app/src/main/java.<your_package_name>/MainActivity.kt

package <your.package.name>

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    private val viewModel = AppViewModel.getInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val context = this as Context

        setContent {
            MainActivityContent(
                viewModel = viewModel,
                onNoteListItemClick = {
                    // TODO: Open note edit form
                },
                onNoteAddClick = {
                    // TODO: Open note create form
                },
            )
        }
    }
}

@Composable
fun MainActivityContent(
    viewModel: AppViewModel,
    onNoteListItemClick: (note: Note) -> Unit,
    onNoteAddClick: () -> Unit,
) {
    val notes = viewModel.notes.value
    MaterialTheme {
        Scaffold(
            topBar = { TopAppBar(title = { Text("My Notes") }) },
            floatingActionButton = {
                ExtendedFloatingActionButton(
                    onClick = { onNoteAddClick() },
                    icon = { Icon(Icons.Filled.Add, contentDescription = "Add") },
                    text = { Text("Add") }
                )
            },
        ) { contentPadding ->
            Box(modifier = Modifier.padding(contentPadding)) {
                NoteList(notes, onNoteListItemClick = { onNoteListItemClick(it) })
            }
        }
    }
}

@Composable
fun NoteListItem(note: Note, onNoteListItemClick: (note: Note) -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = { onNoteListItemClick(note) })
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(text = note.icon, fontSize = 32.sp, modifier = Modifier.size(48.dp))
        Spacer(modifier = Modifier.width(8.dp))
        Column {
            Text(text = note.title, fontSize = 18.sp)
            Spacer(modifier = Modifier.height(4.dp))
            Text(
                text = note.content,
                fontSize = 14.sp,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
            )
        }
    }
}

@Composable
fun NoteList(notes: Map<String, Note>, onNoteListItemClick: (note: Note) -> Unit) {
    LazyColumn {
        items(notes.entries.toList()) { (_, note) ->
            NoteListItem(note = note, onNoteListItemClick = onNoteListItemClick)
        }
    }
}
  1. Las notes ahora se obtienen de AppViewModel.
  2. En lugar de definir los eventos de clic en componibles, los pasamos como argumentos.
  3. Usamos Compose para diseñar la interfaz de usuario. Para hacerlo más elegante, incorporamos MaterialTheme con el diseño Scaffold.

Si reconstruye la aplicación ahora, debería ver la lista de las notas “codificadas” en la pantalla.

Back4app Notes App List

Actividad de formulario de nota

En esta sección, agregaremos una nueva actividad que permitirá a los usuarios agregar y editar notas.

Comience creando una nueva clase llamada FormActivity con los siguientes contenidos:

// app/src/main/java.<your_package_name>/FormActivity.kt

package <your.package.name>

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp

class FormActivity : ComponentActivity() {
    private val viewModel = AppViewModel.getInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val objectId = intent.getStringExtra("objectId")
        val note = if (objectId !== null) viewModel.notes.value[objectId] else null

        setContent {
            FormActivityContent(
                note,
                onNoteAddClick = { icon: String, title: String, content: String ->
                    if (note !== null) return@FormActivityContent
                    val newNote = Note(
                        icon = icon,
                        title = title,
                        content = content,
                    )
                    newNote.objectId = Note.generateObjectId()
                    viewModel.notes.value += (newNote.objectId!! to newNote)
                    finish()
                },
                onNoteSaveClick = { icon: String, title: String, content: String ->
                    if (note === null) return@FormActivityContent
                    val updatedNote = note.copy()
                    updatedNote.icon = icon
                    updatedNote.title = title
                    updatedNote.content = content
                    viewModel.notes.value += (updatedNote.objectId!! to updatedNote)
                    finish()
                },
                onNoteDeleteClick = {
                    if (note === null) return@FormActivityContent
                    viewModel.notes.value = viewModel.notes.value.filter {
                        it.value.objectId != note.objectId
                    }
                    finish()
                },
            )
        }
    }
}

@Composable
fun FormActivityContent(
    note: Note?,
    onNoteAddClick: (icon: String, title: String, content: String) -> Unit,
    onNoteSaveClick: (icon: String, title: String, content: String) -> Unit,
    onNoteDeleteClick: () -> Unit,
) {
    MaterialTheme {
        Scaffold(
            topBar = {
                TopAppBar(title = { Text(note?.let { "Edit Note" } ?: ("Add Note")) })
            },
            floatingActionButton = {
                if (note !== null) {
                    ExtendedFloatingActionButton(
                        onClick = { onNoteDeleteClick() },
                        icon = { Icon(Icons.Filled.Delete, "Delete") },
                        text = { Text("Delete") },
                    )
                }
            },
        ) { contentPadding ->
            Box(modifier = Modifier.padding(contentPadding)) {
                NoteForm(note = note, onNoteSave = { icon, title, content ->
                    if (note === null) {
                        onNoteAddClick(icon, title, content)
                    } else {
                        onNoteSaveClick(icon, title, content)
                    }
                })
            }
        }
    }
}

@Composable
fun NoteForm(
    note: Note?,
    onNoteSave: (icon: String, title: String, content: String) -> Unit
) {
    var icon by remember { mutableStateOf(TextFieldValue(note?.icon ?: "")) }
    var title by remember { mutableStateOf(TextFieldValue(note?.title ?: "")) }
    var content by remember { mutableStateOf(TextFieldValue(note?.content ?: "")) }
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        TextField(
            label = { Text(text = "Icon") },
            value = icon,
            onValueChange = { icon = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        TextField(
            label = { Text(text = "Title") },
            value = title,
            onValueChange = { title = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        TextField(
            label = { Text(text = "Content") },
            value = content,
            onValueChange = { content = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = { onNoteSave(icon.text, title.text, content.text) },
            Modifier.fillMaxWidth()
        ) {
            Text(text = "Save")
        }
    }
}
  1. Este formulario se utiliza tanto para agregar como para editar notas. Para determinar la acción, comparamos objectId == null. En el caso de null, es una acción de agregar, de lo contrario, una acción de edición.
  2. Si objectId !== null, obtenemos la note del estado y completamos el formulario.
  3. Para que MutableState funcione correctamente, tuvimos que tratar su contenido como inmutable. Es por eso que a veces copiamos los contenidos en lugar de modificarlos.
  4. Manejamos el estado del formulario Compose a través de mutableStateOf().

A continuación, registre FormActivity en la parte inferior de application en AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application>
        <!-- ... -->
        <activity android:name=".FormActivity"/>
    </application>

</manifest>

Por último, cree una nueva Intent en onNoteListItemClick y onNoteAddClick en MainActivity.kt:

// app/src/main/java.<your_package_name>/MainActivity.kt

class MainActivity : ComponentActivity() {
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        setContent {
            MainActivityContent(
                viewModel = viewModel,
                onNoteListItemClick = {
                    // triggers the edit action, since `objectId` is provided
                    val intent = Intent(context, FormActivity::class.java)
                    intent.putExtra("objectId", it.objectId)
                    context.startActivity(intent)
                },
                onNoteAddClick = {
                    // triggers the add action, since no `objectId` is present
                    val intent = Intent(context, FormActivity::class.java)
                    context.startActivity(intent)
                },
            )
        }
    }
}

No olvide importar Intent en la parte superior del archivo:

import android.content.Intent

Si reconstruye la aplicación, notará que ahora tenemos una aplicación que funciona. La aplicación nos permite agregar notas, editarlas y eliminarlas.

El único problema es que reiniciar la aplicación restablece su estado (a las notas “codificadas”).En la siguiente sección, conectaremos la aplicación al backend de Back4app. Eso nos permitirá conservar el estado y sincronizarlo entre varios dispositivos.

Android Notes App Edit Preview

Instalar el SDK de Parse

Como sabrá, Back4app se basa en la plataforma Parse. Si queremos interactuar con la base de datos Back4app o Back4app en general, tenemos que instalar el Parse SDK.

Comience agregando el repositorio de JitPack a settings.gradle:

// settings.gradle

pluginManagement {
    repositories {
        // ...
        maven { url "https://jitpack.io" }
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        // ...
        maven { url "https://jitpack.io" }
    }
}

A continuación, agregue Android Parse SDK al build.gradle del nivel de la aplicación:

// app/build.gradle

dependencies {
    // ...
    implementation "com.github.parse-community.Parse-SDK-Android:parse:4.2.0"
}

Sincronice la configuración de Gradle y asegúrese de que no haya errores.

Configurar el SDK de Parse

Para conectarse al backend de Back4app, deberá proporcionar Parse SDK con su ID de aplicación y clave de cliente. Para obtener sus credenciales, vaya a su aplicación Back4app y seleccione “Configuración de la aplicación > Seguridad y claves” en la barra lateral.

Luego agréguelos a su strings.xml así:

<!-- app/src/main/res/values/strings.xml -->

<resources>
    <string name="app_name">back4app-android-app</string>
    <string name="back4app_server_url">https://parseapi.back4app.com/</string>
    <string name="back4app_app_id">your_parse_app_id</string>
    <string name="back4app_client_key">your_parse_client_key</string>
</resources>

Asegúrese de reemplazar your_parse_app_id y your_parse_client_key con sus credenciales.

A continuación, modifique su AndroidManifest.xml para habilitar el acceso a Internet y adjunte metadatos de credenciales:

<!-- app/src/main/AndroidManifest.xml -->

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- these two permissions enable internet access -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application>
        <!-- ... -->

        <!-- newly added metadata -->
        <meta-data
            android:name="com.parse.SERVER_URL"
            android:value="@string/back4app_server_url" />
        <meta-data
            android:name="com.parse.APPLICATION_ID"
            android:value="@string/back4app_app_id" />
        <meta-data
            android:name="com.parse.CLIENT_KEY"
            android:value="@string/back4app_client_key" />
    </application>

</manifest>

Lo último que tenemos que hacer es inicializar Parse. Para asegurarnos de que Parse se inicialice antes que cualquier actividad, crearemos una nueva clase llamada App, que hereda de la clase Application.

Cree App.kt e inicialice Parse así:

// app/src/main/java/<your_package_name>/App.kt

package <your.package.name>

import android.app.Application
import com.parse.Parse

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        Parse.initialize(
            Parse.Configuration.Builder(this)
                .applicationId(getString(R.string.back4app_app_id))
                .clientKey(getString(R.string.back4app_client_key))
                .server(getString(R.string.back4app_server_url))
                .build()
        )
    }
}

Luego registre la clase App en AndroidManifest.xml:

<!-- app/src/main/AndroidManifest.xml -->

<application
    android:name=".App"
    ...
>
    <!-- ... -->
</application>

Reconstruya la aplicación una vez más y verifique la ventana de Logcat para ver si hay errores. Si no hay errores, la conexión a Back4app ha sido exitosa.

Cargar notas desde Back4app

Lo último que tenemos que hacer antes de que nuestra aplicación esté completa es cargar las notas de la base de datos de Back4app y ver cómo usar Parse en la práctica.

Comience por navegar a AppViewModel. Elimine los datos del mapa y agregue el bloque init:

// app/src/main/java/<your_package_name>/AppViewModel.kt

package <your.package.name>

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class AppViewModel : ViewModel() {
    val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf())

    init {
        val query = com.parse.ParseQuery.getQuery<com.parse.ParseObject>("Note")
        query.orderByDescending("createdAt")
        query.findInBackground { notes, e ->
            if (e == null) {
                for (parseNote in notes) {
                    val note = Note(
                        objectId = parseNote.objectId,
                        icon = parseNote.getString("icon")!!,
                        title = parseNote.getString("title")!!,
                        content = parseNote.getString("content")!!,
                    )
                    this.notes.value += (note.objectId!! to note)
                }
            } else {
                println("Error: ${e.message}")
            }
        }
    }

    companion object {
        // ...
    }
}

Este código usa el SDK de Parse para obtener las notas de las bases de datos, las transforma en la clase de datos Note y las guarda en el mapa.

A continuación, agregue los siguientes tres métodos a Note:

// app/src/main/java/<your_package_name>/Note.kt

package <your.package.name>

import com.parse.ParseObject
import com.parse.ParseQuery

data class Note(
    var objectId: String? = null,
    var icon: String,
    var title: String,
    var content: String,
) {
    fun addToParse(callback: (objectId: String) -> Unit) {
        if (objectId !== null) throw Exception("Note is already saved to Parse!")

        val parseNote = ParseObject("Note")
        parseNote.put("icon", icon)
        parseNote.put("title", title)
        parseNote.put("content", content)

        parseNote.saveInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            objectId = parseNote.objectId
            callback(parseNote.objectId)
        }
    }

    fun updateToParse(callback: (objectId: String) -> Unit) {
        if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")

        val query = ParseQuery.getQuery<ParseObject>("Note")
        val parseNote = query.get(objectId)
        parseNote.put("icon", icon)
        parseNote.put("title", title)
        parseNote.put("content", content)

        parseNote.saveInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            callback(parseNote.objectId)
        }
    }

    fun deleteFromParse(callback: () -> Unit) {
        if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")

        val query = ParseQuery.getQuery<ParseObject>("Note")
        val parseNote = query.get(objectId)
        parseNote.deleteInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            callback()
        }
    }
}
  1. addToParse() agrega una nueva nota al servidor Parse con sus detalles. Si tiene éxito, almacena el identificador único de la nota y notifica cuando termina.
  2. updateToParse() actualiza la información de una nota existente en el servidor Parse. Si tiene éxito, señala la finalización después de realizar los cambios.
  3. deleteFromParse() elimina una nota guardada del servidor Parse. Si tiene éxito, confirma la eliminación cuando finaliza.

Por último, modifique los métodos de clic en FormActivity para invocar los métodos recién definidos:

// app/src/main/java/<your_package_name>/NoteFormActivity.kt

class FormActivity : ComponentActivity() {
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        setContent {
            FormActivityContent(
                note,
                onNoteAddClick = { icon: String, title: String, content: String ->
                    if (note !== null) return@FormActivityContent
                    val newNote = Note(
                        icon = icon,
                        title = title,
                        content = content,
                    )
                    newNote.addToParse {
                        viewModel.notes.value += (it to newNote)
                        finish()
                    }
                },
                onNoteSaveClick = { icon: String, title: String, content: String ->
                    if (note === null) return@FormActivityContent
                    val updatedNote = note.copy()
                    updatedNote.icon = icon
                    updatedNote.title = title
                    updatedNote.content = content
                    updatedNote.updateToParse {
                        viewModel.notes.value += (it to updatedNote)
                        finish()
                    }
                },
                onNoteDeleteClick = {
                    if (note === null) return@FormActivityContent
                    viewModel.notes.value = viewModel.notes.value.filter {
                        it.value.objectId != note.objectId
                    }
                    note.deleteFromParse {
                        finish()
                    }
                },
            )
        }
    }
}

¡Eso es todo!

La aplicación ahora funciona completamente y está sincronizada con el backend de Back4app. Intente jugar con la aplicación cambiando los datos y verificando si los cambios se reflejan en la vista de la base de datos.

Conclusión

En este artículo, creamos con éxito un backend móvil y nos conectamos a él desde nuestra aplicación de Android. Utilizamos la solución BaaS de Back4app para el backend y, en el frontend, utilizamos Kotlin con Jetpack Compose.

A estas alturas, debería tener una comprensión decente de cómo funcionan los backend móviles y poder crear el suyo propio. Vea el código fuente final en el repositorio back4app-android-app.

Preguntas frecuentes

¿Qué es Android?

Android es un sistema operativo gratuito y de código abierto basado en Linux. Fue diseñado principalmente para dispositivos móviles, pero ahora también se usa para televisores inteligentes, consolas de juegos y más. Tiene una cuota de mercado móvil del 70% y más de 3 mil millones de usuarios activos mensuales.

¿Cuáles son los beneficios del desarrollo de Android?

– Multiplataforma 
– Mercado enorme 
– Personalización 
– Comunidad

¿Cuáles son las limitaciones del desarrollo de Android?

– Seguridad 
– Complejidad 
– Aplicaciones premium

¿Cómo construir un backend para una aplicación de Android?

1. Regístrese para obtener una cuenta gratuita de Back4app
2. Cree una aplicación basada en BaaS.
3. Diseñe las clases de la base de datos.
4. Arranque una aplicación de Android a través de Android Studio
5. Instale el SDK de Parse y conéctese a Back4app. 
6. Implemente la UI/UX y la funcionalidad de la aplicación.


Leave a reply

Your email address will not be published.