feat(auto): browse and play local music folders in Android Auto [size:exception]
Phase 1: pick a device folder via SAF (persisted grant, no new permission), browse its nested subfolders/tracks as a 5th Android Auto root folder (hidden until configured), and play tracks through the existing pipeline (EQ, art rotation, cold-start-safe source). No metadata/sort/filter/shuffle yet -- filename is the title, generic rotating art is the placeholder; deferred to a follow-up phase. Adds a new pluriwave/file_actions native method (listAudioChildren) and an onActivityResult override in MainActivity for the SAF folder picker -- both static-review-only, no Android build available here.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/// Local file-system node returned by the native `listAudioChildren`
|
||||
/// channel call (Design "Interfaces / Contracts"): either a subfolder or an
|
||||
/// audio file, one SAF tree level deep. Pure DTO — no behavior, so no unit
|
||||
/// tests are warranted for it on its own (exercised indirectly through its
|
||||
/// consumers, e.g. `ConstructorArbolAuto.itemsLocales`).
|
||||
class NodoLocal {
|
||||
const NodoLocal({
|
||||
required this.documentId,
|
||||
required this.nombre,
|
||||
required this.esDirectorio,
|
||||
});
|
||||
|
||||
/// Opaque SAF document id, unique within the picked tree. May itself
|
||||
/// contain `:`/`/` (Design "Prefix stripped by length"), so callers must
|
||||
/// never split/parse it — only wrap it verbatim in a media id.
|
||||
final String documentId;
|
||||
|
||||
/// Raw on-device filename (or folder name), NOT yet title-stripped.
|
||||
final String nombre;
|
||||
|
||||
/// Whether this node is a browsable subfolder (`true`) or a playable
|
||||
/// audio file (`false`).
|
||||
final bool esDirectorio;
|
||||
}
|
||||
|
||||
/// Minimal playable local track (Design "Phase 1 minimal shape" — no
|
||||
/// artist/album/duration metadata per spec's "Not in this delta"). Pure
|
||||
/// DTO — no behavior, so no unit tests are warranted for it on its own.
|
||||
class PistaLocal {
|
||||
const PistaLocal({
|
||||
required this.documentId,
|
||||
required this.titulo,
|
||||
required this.contentUri,
|
||||
});
|
||||
|
||||
/// Opaque SAF document id for this track.
|
||||
final String documentId;
|
||||
|
||||
/// Display title, already computed by the caller (filename minus
|
||||
/// extension, or a derived fallback — see `navegacion_auto.dart`).
|
||||
final String titulo;
|
||||
|
||||
/// Playable `content://` URI resolved via
|
||||
/// `FuenteMusicaLocalAuto.uriContenidoDePista`.
|
||||
final String contentUri;
|
||||
}
|
||||
Reference in New Issue
Block a user