Repository navigation
Arquitetura
victor-kauan-coder edited this page Sep 26, 2026
·
1 revision
App Android nativo em Kotlin + Jetpack Compose, uma Activity, sem backend. Reprodução com AndroidX Media3 (ExoPlayer + MediaSession).
com.songv.app
├── SongVApp Application: guarda os repositórios e um escopo para gravações
├── model/ Musica, Album, Artista, Playlist, Letra, LinhaLetra
├── id3/ Id3Parser — parser ID3v2 próprio (ver "Formato das tags ID3")
├── letra/
│ ├── Lrc parser/gerador de LRC, normalização, busca binária da linha atual
│ ├── LetraRepository escolhe a fonte da letra, busca na LRCLIB, importa .lrc
│ ├── TradutorLetra tradução em blocos + romanização + cache em disco
│ └── Rede HttpURLConnection mínimo (sem bibliotecas)
├── data/
│ ├── MusicaRepository varredura do MediaStore + índice em disco
│ ├── CapaRepository capas: disco (512 px), memória (LRU), alta resolução
│ ├── CapaProvider entrega capas à notificação/tela de bloqueio
│ └── PreferenciasRepository DataStore: tema, favoritas, playlists, histórico, sessão…
├── player/
│ ├── PlayerHolder ExoPlayer + MediaSession únicos do processo
│ ├── MusicPlaybackService MediaSessionService (notificação e foreground via Media3)
│ ├── PlayerViewModel estado da biblioteca, fila, letra, tradução; comandos
│ └── TimerSono timer de sono com fade-out
└── ui/
├── MainActivity permissões, tema, casca com abas, player/fila sobrepostos
├── Navegacao abas, pilha de telas e folhas (sobrevive à rotação)
├── theme/ cores, tipografia, formas
├── components/ capa, linhas, botões, folhas, mini player, reordenação
└── screens/ Início, Buscar, Biblioteca, Álbum/Artista/Playlist, Player, Letra, Fila, Configurações
flowchart LR
MS[(MediaStore)] --> MR[MusicaRepository]
MP3[(arquivos MP3)] --> ID3[Id3Parser]
ID3 --> MR
MR -->|índice em disco| MR
MR --> VM[PlayerViewModel]
ID3 --> LR[LetraRepository]
LRCLIB((LRCLIB)) --> LR
LR --> VM
GT((Google Tradutor)) --> TR[TradutorLetra] --> VM
VM -->|StateFlow| UI[Compose]
UI -->|comandos| VM
VM <--> EXO[ExoPlayer]
EXO --- SES[MediaSession] --- SVC[MusicPlaybackService]
SVC --> NOT[Notificação / tela de bloqueio]
CR[CapaRepository] --> UI
CR --> CP[CapaProvider] --> NOT
-
Um único player.
PlayerHoldercria o ExoPlayer e a MediaSession uma vez por processo. A UI comanda o player direto; o serviço registra a sessão (addSession) e o Media3 cuida da notificação e de entrar em foreground só quando toca. (A 1.0 iniciava o serviço em foreground sem notificação e o sistema derrubava o app.) -
O player é a fonte da verdade da fila. Cada item tem um
mediaIdúnico (<id>#<contador>); o ViewModel reconstrói a fila a partir daTimeline, na ordem do modo aleatório (getNextWindowIndex(..., shuffle)). Tocar a seguir e reordenar no aleatório reescrevem aShuffleOrder. -
Estados separados.
biblioteca,reproducao,letra,preferenciaseprogressosão fluxos distintos. A posição (progresso) só roda enquanto alguém a observa — antes ela estava no estado geral e recompunha o app inteiro 5×/s. - Nada de reiniciar a música por acidente. Carregar a biblioteca é idempotente (girar a tela não recarrega) e recarregar nunca mexe na fila tocando.
-
Leitura de tags rápida. A tag é lida numa única leitura sequencial (o armazenamento compartilhado passa por FUSE; muitas leituras pequenas custavam ~1 s por arquivo). O resultado vai para
files/biblioteca.json; na próxima abertura só arquivos novos/modificados são relidos. - Sessão. Fila, posição, ordem aleatória e repetição são salvas a cada troca de faixa, pausa, a cada 20 s tocando e ao sair; ao abrir, a fila volta pausada.
| O quê | Onde |
|---|---|
| Preferências, favoritas, playlists, histórico, contagens, sessão, ajustes de sincronia | DataStore configuracoes
|
| Índice da biblioteca | files/biblioteca.json |
| Letras buscadas/importadas | files/letras/<id>.lrc |
| Traduções | files/traducoes/<idioma>_<hash>.json |
| Capas 512 px |
cache/capas/ (o sistema pode limpar; são recriadas) |
SongV · feito por Victor K · repositório · licença MIT