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.
Kotlin rápido
| val x = 1 · var y = 2 | Inmutable · mutable |
|---|---|
| String? · x?.length ?: 0 | Tipo 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 * r | Funció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 Estado | Jerarquía cerrada, when exhaustivo |
| suspend fun · launch { } · withContext(Dispatchers.IO) | Corrutinas |
Ciclo de vida de una Activity
| onCreate | Se crea: preparar la interfaz |
|---|---|
| onStart · onResume | Visible · en primer plano |
| onPause · onStop | Pierde el foco · deja de verse |
| onDestroy | Se destruye (también al girar la pantalla) |
| ViewModel | Sobrevive al giro; guarda el estado de la pantalla |
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óvilesViewModel 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óvilesPermisos y multimedia
| <uses-permission android:name="…CAMERA"/> | Declarar en AndroidManifest.xml |
|---|---|
| rememberLauncherForActivityResult(RequestPermission()) | Pedirlo en tiempo de ejecución |
| TakePicturePreview · PickVisualMedia | Cámara · selector de fotos sin permisos |
| MediaPlayer.create(ctx, R.raw.sonido).start() | Audio sencillo; release() al terminar |
| SoundPool | Efectos cortos y repetidos de juegos |
| ExoPlayer (Media3) | Vídeo y streaming |
| SensorManager + SensorEventListener | Acelerómetro, giroscopio… |
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 3DConceptos de juegos
| Escena · nodo (Godot) · GameObject (Unity) | Piezas del juego organizadas en árbol |
|---|---|
| Sprite · tilemap | Imagen 2D · mapa de baldosas |
| Colisionador · cuerpo rígido | Forma 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 estados | Quieto, corriendo, saltando… y sus transiciones |
apuntesdam.com/subject/prog-multimedia/chuleta
Chuletas de otras asignaturas
Entornos de DesarrolloProgramaciónLenguajes de MarcasBases de DatosSistemas InformáticosAcceso a DatosDesarrollo de InterfacesProgramación de Servicios y ProcesosSistemas de Gestión EmpresarialDesarrollo Web en Entorno ClienteDesarrollo Web en Entorno ServidorDespliegue de Aplicaciones WebDiseño de Interfaces Web