audio_service 0.6.1

audio_service #

Play audio in the background.

  • Continues playing while the screen is off or the app is in the background
  • Control playback from your Flutter UI, notifications, lock screen, headset, Wear OS or Android Auto
  • Drive audio playback from Dart code

This plugin wraps around your existing Dart audio code to allow it to run in the background, and also respond to media button clicks on the lock screen, notifications, control center, headphone buttons and other supported remote control devices. This is necessary for a whole range of media applications such as music and podcast players, text-to-speech readers, navigators, etc.

This plugin is audio agnostic. It is designed to allow you to use your favourite audio plugins, such as just_audio, flutter_radio, flutter_tts, and others. It simply wraps a special isolate around your existing audio code so that it can run in the background and enable remote control interfaces.

Note that because your app's UI and your background audio task will run in separate isolates, they do not share memory. They communicate through the message passing APIs provided by audio_service.

NEW: This release includes a partially working "alpha" iOS implementation. If you'd like to help with any missing features, join us on GitHub issue #10.

FeatureAndroidiOS
start/stop
play/pause
headset click
seek
skip next/prev
FF/rewind
rate
custom actions(untested)
notifications/control center(partial)
lock screen controls(partial)
album art
queue management
runs in background
Handle phonecall interruptions
Android Auto(untested)

Example #

audio_service provides two sets of APIs: one for your main UI isolate (AudioService), and one for your background audio isolate (AudioServiceBackground).

UI code #

This code runs in the main UI isolate:

AudioService.connect();    // When UI becomes visible
AudioService.start(        // When user clicks button to start playback
  backgroundTaskEntrypoint: myBackgroundTaskEntrypoint,
  androidNotificationChannelName: 'Music Player',
  androidNotificationIcon: "mipmap/ic_launcher",
);
AudioService.pause();      // When user clicks button to pause playback
AudioService.play();       // When user clicks button to resume playback
AudioService.disconnect(); // When UI is gone

The full example on GitHub should be consulted for tips on how to hook connect and disconnect into your widget's lifecycle.

Background code #

This code runs in a background isolate, and is the code that is guaranteed to continue running even if your UI is gone:

void myBackgroundTaskEntrypoint() {
  AudioServiceBackground.run(() => MyBackgroundTask());
}

class MyBackgroundTask extends BackgroundAudioTask {
  @override
  Future<void> onStart() async {
    // Your custom dart code to start audio playback.
    // NOTE: The background audio task will shut down
    // as soon as this async function completes.
  }
  @override
  void onStop() {
    // Your custom dart code to stop audio playback.
  }
  @override
  void onPlay() {
    // Your custom dart code to resume audio playback.
  }
  @override
  void onPause() {
    // Your custom dart code to pause audio playback.
  }
  @override
  void onClick(MediaButton button) {
    // Your custom dart code to handle a media button click.
  }
}

The full example on GitHub demonstrates how to fill in these callbacks to do audio playback and also text-to-speech.

Android setup #

These instructions assume that your project follows the new project template introduced in Flutter 1.12. If your project was created prior to 1.12 and uses the old project structure, you can either view a previous version of this README on GitHub, or update your project to follow the new project template.

  1. Edit your project's AndroidManifest.xml file to declare the permission to create a wake lock, and add component entries for the <service> and <receiver>:
<manifest ...>
  <uses-permission android:name="android.permission.WAKE_LOCK"/>
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
  
  <application ...>
    
    ...
    
    <service android:name="com.ryanheise.audioservice.AudioService">
      <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService" />
      </intent-filter>
    </service>

    <receiver android:name="androidx.media.session.MediaButtonReceiver" >
      <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
      </intent-filter>
    </receiver> 
  </application>
</manifest>
  1. Any icons that you want to appear in the notification (see the MediaControl class) should be defined as Android resources in android/app/src/main/res. Here you will find a subdirectory for each different resolution:
drawable-hdpi
drawable-mdpi
drawable-xhdpi
drawable-xxhdpi
drawable-xxxhdpi

You can use Android Asset Studio to generate these different subdirectories for any standard material design icon.

Starting from Flutter 1.12, you will also need to disable the shrinkResources setting in your android/app/build.gradle file, otherwise your icon resources will be removed during the build:

android {
    compileSdkVersion 28

    ...

    buildTypes {
        release {
            signingConfig ...
            shrinkResources false // ADD THIS LINE
        }
    }
}
  1. (Optional) Versions of Flutter since 1.12 have a memory leak that affects this plugin. It will be fixed in an upcoming Flutter release but until then you can work around it by overriding the following method in your MainActivity class:
public class MainActivity extends FlutterActivity {
  /** This is a temporary workaround to avoid a memory leak in the Flutter framework */
  @Override
  public FlutterEngine provideFlutterEngine(Context context) {
    // Instantiate a FlutterEngine.
    FlutterEngine flutterEngine = new FlutterEngine(context.getApplicationContext());

    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.getDartExecutor().executeDartEntrypoint(
      DartExecutor.DartEntrypoint.createDefault()
    );

    return flutterEngine;
  }
}

Alternatively, if you use a cached flutter engine (as per these instructions), you will need to change the instantiation code from new FlutterEngine(this) to new FlutterEngine(getApplicationContext()).

iOS setup #

Insert this in your Info.plist file:

	<key>UIBackgroundModes</key>
	<array>
		<string>audio</string>
	</array>

The example project may be consulted for context.

0.6.1 #

  • Option to stop service on closing task (Android).

0.6.0 #

  • Migrated to V2 embedding API (Flutter 1.12).

0.5.7 #

  • Destroy isolates after use.

0.5.6 #

  • Support Flutter 1.12.

0.5.5 #

  • Bump sdk version to 2.6.0.

0.5.4 #

  • Fix Android memory leak.

0.5.3 #

  • Support Queue, album art and other missing features on iOS.

0.5.2 #

  • Update documentation and example.

0.5.1 #

  • Playback state broadcast on connect (iOS).

0.5.0 #

  • Partial iOS support.

0.4.2 #

  • Option to call stopForeground on pause.

0.4.1 #

  • Fix queue support bug

0.4.0 #

  • Breaking change: AudioServiceBackground.run takes a single parameter.

0.3.1 #

  • Update example to disconnect when pressing back button.

0.3.0 #

  • Breaking change: updateTime now measured since epoch instead of boot time.

0.2.1 #

  • Streams use RxDart BehaviorSubject.

0.2.0 #

  • Migrate to AndroidX.

0.1.1 #

  • Bump targetSdkVersion to 28
  • Clear client-side metadata and state on stop.

0.1.0 #

  • onClick is now always called for media button clicks.
  • Option to set notifications as ongoing.

0.0.15 #

  • Option to set subText in notification.
  • Support media item ratings

0.0.14 #

  • Can update existing media items.
  • Can specify order of Android notification compact actions.
  • Bug fix with connect.

0.0.13 #

  • Option to preload artwork.
  • Allow client to browse media items.

0.0.12 #

  • More options to customise the notification content.

0.0.11 #

  • Breaking API changes.
  • Connection callbacks replaced by a streams API.
  • AudioService properties for playbackState, currentMediaItem, queue.
  • Option to set Android notification channel description.
  • AudioService.customAction awaits completion of the action.

0.0.10 #

  • Bug fixes with queue management.
  • AudioService.start completes when the background task is ready.

0.0.9 #

  • Support queue management.

0.0.8 #

  • Bug fix.

0.0.7 #

  • onMediaChanged takes MediaItem parameter.
  • Support playFromMediaId, fastForward, rewind.

0.0.6 #

  • All APIs address media items by String mediaId.

0.0.5 #

  • Show media art in notification and lock screen.

0.0.4 #

  • Support and example for playing TextToSpeech.
  • Click notification to launch UI.
  • More properties added to MediaItem.
  • Minor API changes.

0.0.3 #

  • Pause now keeps background isolate running
  • Notification channel id is generated from package name
  • Updated example to use audioplayer plugin
  • Fixed media button handling

0.0.2 #

  • Better connection handling.

0.0.1 #

  • Initial release.

example/README.md

audio_service_example #

This example demonstrates how to play an audio file or text-to-speech in the background.

Getting Started #

For help getting started with Flutter, view our online documentation.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  audio_service: ^0.6.1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:audio_service/audio_service.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
91
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
96
Learn more about scoring.

We analyzed this package on Feb 21, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.5
  • Flutter: 1.12.13+hotfix.7

Health suggestions

Format lib/audio_service.dart.

Run flutter format to format lib/audio_service.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.6.0 <3.0.0
flutter 0.0.0
flutter_isolate ^1.0.0+11 1.0.0+11
rxdart ^0.23.1 0.23.1
Transitive dependencies
charcode 1.1.3
collection 1.14.11 1.14.12
convert 2.1.1
crypto 2.1.4
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
uuid 2.0.4
vector_math 2.0.8