DEV Community

 AppInitDev
AppInitDev

Posted on

Música local en Android: por qué MediaStore y Media3 resuelven problemas diferentes

Música local en Android: por qué MediaStore y Media3 resuelven problemas diferentes

Los usuarios que guardan colecciones MP3 o FLAC necesitan descubrir archivos y reproducirlos sin exigir una cuenta o una conexión de red. Esas tareas no deberían tratarse como si fueran la misma capa del sistema.

El problema y el alcance del ejemplo

La ficha de Amplify: Reproductor Hi-Res resume su función así: «Reproductor de música sin conexión con ecualizador de 10 bandas y FLAC.» Amplify anuncia reproducción offline, FLAC y ecualización de diez bandas. En este ejemplo aislamos la obtención de una URI de audio con MediaStore; después esa URI puede consumirse con Media3. No se afirma que Amplify use internamente esas bibliotecas.

Cómo reproducir la idea

En un proyecto Kotlin Android, declara el permiso de lectura de audio correspondiente a la versión del sistema (READ_MEDIA_AUDIO en Android 13+) y solicítalo en ejecución antes de hacer la consulta. La búsqueda debe ejecutarse fuera del hilo principal.

import android.content.ContentUris
import android.content.Context
import android.net.Uri
import android.os.Build
import android.provider.MediaStore

fun audioUris(context: Context): List<Uri> {
    val base = if (Build.VERSION.SDK_INT >= 29) {
        MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
    } else {
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    }
    val projection = arrayOf(MediaStore.Audio.Media._ID)
    val result = mutableListOf<Uri>()
    context.contentResolver.query(base, projection, null, null, null)?.use { c ->
        val idIndex = c.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
        while (c.moveToNext()) {
            result += ContentUris.withAppendedId(base, c.getLong(idIndex))
        }
    }
    return result
}

// Después, en una Activity con permiso y Media3 configurado:
// val player = ExoPlayer.Builder(this).build()
// player.setMediaItem(MediaItem.fromUri(audioUris(this).first()))
// player.prepare()
// player.play()
// player.release() cuando termine su ciclo de vida.
Enter fullscreen mode Exit fullscreen mode

Qué demuestra el código

La lista almacena identificadores de contenido (content://), no rutas absolutas. En Android 10+ usamos la colección de volúmenes externos compartidos para cubrir más de una ubicación cuando el sistema las indexa. Esto facilita trabajar con el modelo de almacenamiento moderno. El reproductor debe manejar la eliminación de archivos y las URI que dejan de estar disponibles.

Pruebas recomendadas

Copia un MP3 y un FLAC de prueba al dispositivo, comprueba su indexación, concede permiso y compara las URI detectadas. Activa modo avión y valida que el acceso local no necesita Internet. Evita llamar first() sin comprobar que la lista contiene elementos.

Límites que conviene reconocer

No se implementa cola, reproducción en segundo plano, etiquetas, procesamiento DSP ni verificación bit-perfect. El hecho de poder decodificar FLAC tampoco demuestra una salida de audio Hi-Res de extremo a extremo.

Qué aprendemos

Separar descubrimiento multimedia, motor de reproducción y procesamiento de audio simplifica las pruebas y evita atribuir capacidades de hardware al formato del archivo.

Contexto y enlaces del autor

El tema se relaciona con las funciones declaradas públicamente de Amplify: Reproductor Hi-Res, una aplicación Android de AppInitDev. El código anterior es un ejemplo independiente: no se ha inspeccionado el repositorio privado ni se afirma que sea la implementación interna de la app. La referencia aparece al final para ofrecer contexto, no como requisito para completar el tutorial.

Image APPS

Referencia técnica

MediaStore · Media3: formatos

Top comments (0)