audiofileplayer
A Flutter plugin for audio playback. Supports
- Reading audio data from Flutter project assets, locale files, byte arrays, and remote URLs.
- Seek to position.
- Callbacks for loaded audio duration, current position, and playback completion.
- Looping.
- Volume.
- Pause/Resume.
- Multiple audio players, with memory management.
- Background audio playback.
- Setting supported media actions and metadata for the OS's display.
- Custom media buttons in the Android notification.
Getting Started
To use this plugin, add audiofileplayer
as a dependency in your pubspec.yaml file.
Examples
Please see the top of audiofileplayer.dart
for more information, and see the example app showing the following use cases
in action.
One-shot playback
// Play a sound as a one-shot, releasing its resources when it finishes playing.
Audio.load('assets/foo.wav')..play()..dispose();
Re-use an Audio object
// Load from assets, store as a variable.
Audio audio = Audio.load('assets/bar.mp3');
...
/// Use the [Audio];
audio.play();
...
audio.pause();
...
audio.resume();
/// You must call dispose() when the [Audio] will no longer be used (for example, in State.dispose()). Note that
/// [dispose] will not stop playback, but will internally release resources once the audio finishes playing.
audio
..pause();
..dispose();
Use callbacks to get information
Audio audio = Audio.load('assets/baz.mp4',
// Called when audio has finished playing.
onComplete: () => _handleOnComplete(),
// Called when audio has loaded and knows its duration.
onDuration: (double durationSeconds) => _handleDuration(durationSeconds),
// Called repeatedly with updated playback position.
onPosition: (double positionSeconds) => _handleOnPosition(positionSeconds));
The finer points of dispose()
See the header comment of audiofileplayer.dart for more info on using dispose()
.
Using background audio
Setup
To play background audio, you will need to update a few platform-specific files for your app. (For reference, the example app contains all these changes.)
iOS
Enable the "audio" background mode capability in one of two ways:
- Open your app's autogenerated Runner.xcodeproj file in XCode. See this documentation or
- Edit the Info.plist file to add
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
Android
To use the plugin's custom foreground service, add this within the <manifest> tag of your app's AndroidManifest.xml...
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
...and this within the <application> tag of your AndroidManifest.xml.
<service android:name="com.google.flutter.plugins.audiofileplayer.AudiofileplayerService"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
If you'd like to specify custom buttons in the notification (beyond the 'built-in' buttons, which have icons provided), then add icons for them to the "drawable" resource folder(s). These should be approx 32x32 pts in order to display correctly.
Usage
For an Audio object to continue playing while the app is minimized, set the playInBackground
flag when loading.
Audio backgroundAudio = Audio.load('assets/foo.wav', playInBackground = true);
It is up to you to communicate information to the OS, in order to:
- display metadata (title/artist/artwork/etc).
- specify which transport controls are active/supported. This will be reflected in external controllers (bluetooth/watch/auto/etc)
- inform progress bars for display.
- for Android, specify buttons within the notification.
Communicating with the OS's media system is covered by these methods on the AudioSystem singleton instance. See audio_system.dart for full documentation. See the example app for a complete example using all of these.
void setPlaybackState(bool isPlaying, double positionSeconds);
void setMetadata(AudioMetadata metadata);
void setSupportedMediaActions(Set<MediaActionType> actions,;
{double skipIntervalSeconds});
void setAndroidNotificationButtons(List<dynamic> androidMediaButtons,
{List<int> androidCompactIndices})
void stopBackgroundDisplay();
Additional platform-specific notes.
iOS audio category
You can programatically choose from one of three audio categories on iOS. This affects whether audio will play in the background, or when the 'silent' hardware switch is on. See iOS doc.
This plugin supports switching between the 'playback', 'ambient solo', and 'ambient mixed' categories. For audio to play in the background, the category must be set to 'playback' (which is the default).
See the IosAudioCategory
enum, and the setIosAudioCategory
method.
iOS remote audio loading
If your app attempts to load a remote URL that doesn't use HTTPS, e.g.
Audio.loadFromRemoteUrl('http://www.foo.com/bar.mp3)
then you will get a security error.
To allow loading from non-HTTPS URLs, add the NSAppTransportSecurity
entry to your Info.plist
file. iOS doc.
Android remote audio loading
If your app loads remote audio files, you will need this permission in your AndroidManifest.xml
.
<uses-permission android:name="android.permission.INTERNET"/>
Android small icon
If you see a white box in place of the small notification icon it's probably because your app icon doesn't have a transparent background.
You can specify which icon the audiofileplayer
plugin should use by including the following metadata in your AndroidManifest.xml
.
<meta-data android:name="ic_audiofileplayer" android:value="drawable/notification_icon" />
Don't forget to include the icons to your res/drawable-{density}
directories. Example:
Path | Image Size |
---|---|
res/drawable-mdpi/notification_icon.png | 24x24 |
res/drawable-hdpi/notification_icon.png | 36x36 |
res/drawable-xhdpi/notification_icon.png | 48x48 |
res/drawable-xxhdpi/notification_icon.png | 72x72 |
res/drawable-xxxhdpi/notification_icon.png | 96x96 |
res/drawable-xxxhdpi/notification_icon.png | 256x256 |
(The filename notification_icon.png
was just used as an example, you can use any other file as desired.)