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.)