local_audio_scan 0.0.1
local_audio_scan: ^0.0.1 copied to clipboard
Android-only Flutter package for scanning local audio files with album art extraction.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:local_audio_scan/local_audio_scan.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _localAudioScanPlugin = LocalAudioScanner();
List<AudioTrack> _audioTracks = [];
bool _isLoading = false;
bool _hasPermission = false;
@override
void initState() {
super.initState();
_checkPermissions();
}
Future<void> _checkPermissions() async {
final hasPermission = await _localAudioScanPlugin.checkPermission();
setState(() {
_hasPermission = hasPermission;
});
}
Future<void> _requestPermissionsAndScan() async {
final granted = await _localAudioScanPlugin.requestPermission();
setState(() {
_hasPermission = granted;
});
if (granted) {
_scanAudio();
}
}
Future<void> _scanAudio() async {
if (!_hasPermission) return;
setState(() {
_isLoading = true;
});
try {
final tracks = await _localAudioScanPlugin.scanTracks();
setState(() {
_audioTracks = tracks;
});
} catch (e) {
debugPrint('Failed to scan audio: $e');
} finally {
setState(() {
_isLoading = false;
});
}
}
String _formatDuration(int milliseconds) {
final duration = Duration(milliseconds: milliseconds);
final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
return '$minutes:$seconds';
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Local Audio Scanner'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: _scanAudio,
tooltip: 'Refresh Scan',
),
],
),
body: Center(
child: _buildBody(),
),
floatingActionButton: FloatingActionButton(
onPressed: _requestPermissionsAndScan,
tooltip: 'Scan for Audio',
child: const Icon(Icons.music_note),
),
),
);
}
Widget _buildBody() {
if (!_hasPermission) {
return const Text('Permission not granted. Tap the button to request.');
}
if (_isLoading) {
return const CircularProgressIndicator();
}
if (_audioTracks.isEmpty) {
return const Text('No audio tracks found. Tap the button to scan.');
}
return ListView.builder(
itemCount: _audioTracks.length,
itemBuilder: (context, index) {
final track = _audioTracks[index];
return ListTile(
leading: track.artwork != null
? Image.memory(track.artwork!, width: 50, height: 50, fit: BoxFit.cover)
: const Icon(Icons.music_note, size: 50),
title: Text(track.title, maxLines: 1, overflow: TextOverflow.ellipsis),
subtitle: Text(track.artist, maxLines: 1, overflow: TextOverflow.ellipsis),
trailing: Text(_formatDuration(track.duration)),
);
},
);
}
}