-
-
Notifications
You must be signed in to change notification settings - Fork 484
Make sure you have done the following:
- Your background task entrypoint must be a top-level or static function, don't put in the same class.
- If on Android, you must follow the Android setup instructions in the README file.
Make sure you have upgraded your project to the Flutter 1.12 project structure first. If you still get the error, it may be an issue of the specific combination of other plugins you're using. Make sure that the other plugins you're using have also been updated to support Flutter 1.12 (known as the v2 plugin model).
This can result from a conflict with the flutter_tts
plugin, which is also used in the example. (See the open issue #202)
I have not personally used it, but if you do try, please ensure your project has been updated to the Flutter 1.12 project structure first. If you still receive a MissingPluginException
, you can try adding this to your MainActivity.java
(suggestion by @rohansohonee):
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
audioplayers
has both worked and not worked at different times in the past. If it currently does not work, you can contact the author of that plugin and make a feature request.
Relevant information: For an audio player plugin to work with audio_service
there needs to be clearly delineated roles between the two plugins such that only audio_service
controls the various APIs involved in:
- Enabling background execution
- Displaying notifications, lock screen controls, Control Center info, etc.
- Configuring the audio session
- Handling remote controls from headsets, smart watches, car stereos, etc.
- Handling audio focus events (e.g. if another app takes over audio focus temporarily)
If the other plugin does any of these things, the two plugins will overlap in responsibility and things will probably not work. In other words, you will need an audio player plugin that just plays audio, and doesn't take on any of these other responsibilities listed above.
If at present audioplayers
doesn't work for you, you can alternatively try my plugin just_audio
which was designed with this delineation in mind.
The plugin doesn't provide an API for this (yet). However, you can use the standard Dart Isolates API to send arbitrary messages between isolates. Typically, the UI will create a ReceivePort
and then register its SendPort
in the IsolateNameServer
under a particular name:
_receivePort = ReceivePort();
_receivePort.listen((message) {
// handle message in your UI here
});
IsolateNameServer.registerPortWithName(_receivePort.sendPort, PORT_NAME);
Then in your background task, you can find this SendPort
registered in the isolate name server and send messages via it:
SendPort sendPort = IsolateNameServer.lookupPortByName(PORT_NAME);
sendPort?.send(message);
On Android, yes. In your background task, you must override the relevant callbacks for your use case:
/// Called on Android when your app gains the audio focus.
void onAudioFocusGained() {}
/// Called on Android when your app loses audio focus for an unknown
/// duration.
void onAudioFocusLost() {}
/// Called on Android when your app loses audio focus temporarily and should
/// pause audio output for that duration.
void onAudioFocusLostTransient() {}
/// Called on Android when your app loses audio focus temporarily and may
/// lower the audio output volume for that duration.
void onAudioFocusLostTransientCanDuck() {}
The behaviour of focus on Android is documented here.
There is an issue on Android, but there is a workaround. Android requires an active media sessions to route media button events to, and actual audio needs to be played to activate a media session (text-to-speech does not count). One trick is to play a short segment of silent audio to activate the session. You can use AudioServiceBackground.androidForceEnableMediaButtons()
to achieve this.
There is no way to pass parameters on start, but you can use AudioService.customAction(...)
to pass an arbitrary message to the background after it has started. To ensure it has started, you must await the result of AudioService.start
:
if (await AudioService.start(...)) {
AudioService.customAction(...);
}
If code in your background task's onStart
method needs to know the value of those parameters, consider moving that code into your onCustomAction
method.
There is no API for that yet, but you can send arbitrary messages from the UI to your background audio task via a custom action.
If you want to send a message from the UI to your background audio task but it is not one of the predefined messages defined in AudioService
, you can send the message as a custom action. E.g.
// In your UI
AudioService.customAction("setSpeed", 0.5);
And then in your background audio task, implement the onCustomAction
method:
@override
void onCustomAction(String name, dynamic speed) {
_audioPlayer.setSpeed(speed);
}
Note that the parameter of a custom action can be any data structure that can be encoded by the standard message codec.
You cannot update fields in a MediaItem
object since it is immutable, although in the same style as ThemeData.copyWith
, you can use MediaItem.copyWith
to create a copy with some fields modified. e.g.
modifiedMediaItem = mediaItem.copyWith(duration: duration);
If you are updating the current media item in your background audio task, remember to broadcast this change to all clients:
AudioServiceBackground.setMediaItem(modifiedMediaItem);
If you are updating a media item in the queue in your background audio task, remember to broadcast your modified queue to all clients:
myQueue[pos] = modifiedMediaItem;
AudioServiceBackground.setQueue(myQueue);
Because the background audio task is responsible for performing all of your audio logic, if you want to initiate such a change from your presentation logic (i.e. your UI), the UI needs to send a custom action to your background audio task which can then perform the above actions.
Sometimes you may want to try out the latest code on git master, e.g. to try out a bug fix or new feature that hasn't been released yet. To do so, you can temporarily change your pubspec.yaml
file to:
audio_service:
git:
url: https://github.com/ryanheise/audio_service.git
Note that git master is not stable and should not be used in production.