Apuntes DAM

Chuleta de Programación Multimedia y Dispositivos Móviles

Android con Kotlin y Jetpack Compose, arquitectura MVVM, Room, Retrofit, multimedia y bucle de juego con Godot.

Ponte a prueba con un simulacro

Kotlin rápido

val x = 1 · var y = 2Inmutable · mutable
String? · x?.length ?: 0Tipo anulable · llamada segura y elvis
data class Tarea(val id: Int, val texto: String)equals, hashCode, toString y copy gratis
fun area(r: Double) = PI * r * rFunción de una expresión
when (x) { 1 -> …; in 2..5 -> …; else -> … }switch mejorado
lista.filter { it.hecha }.map { it.texto }Lambdas con it
sealed interface EstadoJerarquía cerrada, when exhaustivo
suspend fun · launch { } · withContext(Dispatchers.IO)Corrutinas
Tema: Desarrollo de Aplicaciones Móviles

Ciclo de vida de una Activity

onCreateSe crea: preparar la interfaz
onStart · onResumeVisible · en primer plano
onPause · onStopPierde el foco · deja de verse
onDestroySe destruye (también al girar la pantalla)
ViewModelSobrevive al giro; guarda el estado de la pantalla
Tema: Tecnologías y Plataformas Móviles

Compose

@Composablefun Contador(modifier: Modifier = Modifier) {  var n by rememberSaveable { mutableIntStateOf(0) }  Column(modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally) {    Text("Pulsado $n veces", style = MaterialTheme.typography.titleLarge)    Button(onClick = { n++ }) { Text("Sumar") }  }}LazyColumn { items(tareas, key = { it.id }) { t -> FilaTarea(t) } }

Estado arriba y eventos abajo (state hoisting). remember se pierde al girar; rememberSaveable no.

Tema: Desarrollo de Aplicaciones Móviles

ViewModel con StateFlow

class TareasViewModel(private val repo: TareaRepository) : ViewModel() {  val tareas: StateFlow<List<Tarea>> = repo.todas()    .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())  fun anadir(texto: String) = viewModelScope.launch { repo.insertar(Tarea(0, texto)) }}// En la pantallaval tareas by vm.tareas.collectAsStateWithLifecycle()
Tema: Desarrollo de Aplicaciones Móviles

Room

@Entity data class Tarea(@PrimaryKey(autoGenerate = true) val id: Int, val texto: String)@Dao interface TareaDao {  @Query("SELECT * FROM Tarea ORDER BY id DESC") fun todas(): Flow<List<Tarea>>  @Insert suspend fun insertar(t: Tarea)  @Delete suspend fun borrar(t: Tarea)}@Database(entities = [Tarea::class], version = 1)abstract class AppDb : RoomDatabase() { abstract fun tareaDao(): TareaDao }
Tema: Desarrollo de Aplicaciones Móviles

Retrofit

interface Api {  @GET("posts") suspend fun posts(@Query("userId") id: Int): List<Post>  @POST("posts") suspend fun crear(@Body p: Post): Post}val api = Retrofit.Builder()  .baseUrl("https://jsonplaceholder.typicode.com/")  .addConverterFactory(GsonConverterFactory.create())  .build().create(Api::class.java)

Permiso INTERNET en el manifiesto. Las llamadas, dentro de una corrutina y con try/catch.

Tema: Desarrollo de Aplicaciones Móviles

Permisos y multimedia

<uses-permission android:name="…CAMERA"/>Declarar en AndroidManifest.xml
rememberLauncherForActivityResult(RequestPermission())Pedirlo en tiempo de ejecución
TakePicturePreview · PickVisualMediaCámara · selector de fotos sin permisos
MediaPlayer.create(ctx, R.raw.sonido).start()Audio sencillo; release() al terminar
SoundPoolEfectos cortos y repetidos de juegos
ExoPlayer (Media3)Vídeo y streaming
SensorManager + SensorEventListenerAcelerómetro, giroscopio…
Tema: Multimedia en Aplicaciones Móviles

Navegación

val nav = rememberNavController()NavHost(nav, startDestination = "lista") {  composable("lista") { Lista(onAbrir = { id -> nav.navigate("detalle/$id") }) }  composable("detalle/{id}") { e -> Detalle(e.arguments?.getString("id")) }}
Tema: Desarrollo de Aplicaciones Móviles

Bucle de juego (Godot)

extends CharacterBody2D@export var velocidad := 200.0func _physics_process(delta: float) -> void:    var dir := Input.get_vector("izq", "der", "arriba", "abajo")    velocity = dir * velocidad    move_and_slide()func _on_area_body_entered(body: Node) -> void:    if body.is_in_group("enemigos"):        queue_free()

Multiplicar por delta hace el movimiento independiente de los FPS. _process cada fotograma, _physics_process a ritmo fijo.

Tema: Desarrollo de Juegos 2D y 3D

Conceptos de juegos

Escena · nodo (Godot) · GameObject (Unity)Piezas del juego organizadas en árbol
Sprite · tilemapImagen 2D · mapa de baldosas
Colisionador · cuerpo rígidoForma de choque · objeto con física
Señales (Godot) · eventos (Unity)Avisar sin acoplar nodos
Update · FixedUpdate (Unity)Equivalen a _process y _physics_process
Máquina de estadosQuieto, corriendo, saltando… y sus transiciones
Tema: Motores de Juegos

Chuletas de otras asignaturas