Aura Music Kit
A powerful Flutter plugin for accessing local audio files, retrieving metadata, and handling platform-specific permissions. Perfect for building music player apps without the hassle of writing native code.
✨ Features
- Fetch All Songs — Query audio files from the device’s media library.
- Album Artwork — Retrieve embedded album covers for each track.
- Rich Metadata — Title, artist, album, duration, file path, and more.
- Permission Handling — Automatically requests the right permissions for Android/iOS.
- API-Level Awareness — Uses
READ_MEDIA_AUDIO
for Android 13+,READ_EXTERNAL_STORAGE
for older devices.
⚙️ Platform Setup
Android
Add permissions to android/app/src/main/AndroidManifest.xml
:
<!-- Android 12 and below -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Android 13+ -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
iOS
Add the NSAppleMusicUsageDescription
key to ios/Runner/Info.plist
:
<key>NSAppleMusicUsageDescription</key>
<string>This app needs access to your music library to play songs.</string>
🚀 Installation
Add dependencies in pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
aura_music_kit: ^1.0.0
permission_handler: ^11.0.0
device_info_plus: ^9.0.0
just_audio: ^0.9.36
Run:
flutter pub get
Import:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:aura_music_kit/aura_music_kit.dart';
📋 Usage
1. Handle Permissions
Future<PermissionStatus> _getPermission() async {
if (Platform.isAndroid) {
final sdkInt = (await DeviceInfoPlugin().androidInfo).version.sdkInt;
return sdkInt >= 33 ? Permission.audio.status : Permission.storage.status;
}
return Permission.mediaLibrary.status;
}
Future<void> _requestPermission() async {
PermissionStatus status;
if (Platform.isAndroid) {
final sdkInt = (await DeviceInfoPlugin().androidInfo).version.sdkInt;
status = sdkInt >= 33
? await Permission.audio.request()
: await Permission.storage.request();
} else {
status = await Permission.mediaLibrary.request();
}
if (status.isGranted) {
_fetchMusic();
} else {
// Handle denial
}
}
2. Fetch Music Files
List<Song> _songs = [];
bool _isLoading = true;
Future<void> _fetchMusic() async {
if (!(await _getPermission()).isGranted) return;
final fetchedSongs = await AuraMusicKit.getMusicFiles();
setState(() {
_songs = fetchedSongs;
_isLoading = false;
});
}
3. Display Song List
ListView.builder(
itemCount: _songs.length,
itemBuilder: (context, index) {
final song = _songs[index];
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: SizedBox(
width: 50,
height: 50,
child: song.artwork != null
? Image.memory(song.artwork!, fit: BoxFit.cover)
: const Icon(Icons.music_note, size: 30),
),
),
title: Text(song.title, maxLines: 1, overflow: TextOverflow.ellipsis),
subtitle: Text(song.artist ?? "Unknown Artist",
maxLines: 1, overflow: TextOverflow.ellipsis),
onTap: () {
// Navigate to player
},
);
},
);
🎛 Equalizer Integration (Android)
Player Setup
final _equalizer = AndroidEqualizer();
late AudioPlayer _audioPlayer;
@override
void initState() {
super.initState();
_audioPlayer = AudioPlayer(
audioPipeline: AudioPipeline(androidAudioEffects: [_equalizer]),
);
}
Equalizer UI
IconButton(
icon: const Icon(Icons.equalizer),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => EqualizerScreen(equalizer: _equalizer),
),
);
},
);
EqualizerScreen:
class EqualizerScreen extends StatefulWidget {
final AndroidEqualizer equalizer;
const EqualizerScreen({super.key, required this.equalizer});
@override
State<EqualizerScreen> createState() => _EqualizerScreenState();
}
class _EqualizerScreenState extends State<EqualizerScreen> {
bool _isEnabled = false;
@override
void initState() {
super.initState();
_isEnabled = widget.equalizer.enabled;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Equalizer')),
body: Column(
children: [
SwitchListTile(
title: const Text('Enable Equalizer'),
value: _isEnabled,
onChanged: (v) {
setState(() {
_isEnabled = v;
widget.equalizer.setEnabled(v);
});
},
),
Expanded(
child: FutureBuilder<AndroidEqualizerParameters>(
future: widget.equalizer.parameters,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final params = snapshot.data!;
return ListView(
children: params.bands.map((band) {
return Column(
children: [
Text('${band.centerFrequency.round()} Hz'),
StreamBuilder<double>(
stream: band.gainStream,
builder: (context, snap) {
return Slider(
min: params.minDecibels,
max: params.maxDecibels,
value: snap.data ?? band.gain,
onChanged: !_isEnabled
? null
: (v) => band.setGain(v),
);
},
),
],
);
}).toList(),
);
},
),
),
],
),
);
}
}
📚 API
AuraMusicKit
Method | Description |
---|---|
getMusicFiles() |
Fetches a list of Song objects from the device. |
Song
Property | Type | Description |
---|---|---|
title |
String |
Song title |
artist |
String? |
Song artist |
album |
String? |
Album name |
data |
String |
File path |
artwork |
Uint8List? |
Album cover |
duration |
int? |
Duration (ms) |
🤝 Contributing
Found a bug? Want to add a feature? Open an issue or submit a PR on GitHub.
📄 License
Licensed under the MIT License.