Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork409
Play simultaneously music/audio from assets/network/file directly from Flutter, compatible with android / ios / web / macos, displays notifications
License
florent37/Flutter-AssetsAudioPlayer
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Play music/audio stored in assets files (simultaneously) directly from Flutter (android / ios / web / macos).
You can also use play audio files fromnetwork using their url,radios/livestream andlocal files
Notification can be displayed on Android & iOS, and bluetooth actions are handled
flutter:assets: -assets/audios/
AssetsAudioPlayer.newPlayer().open(Audio("assets/audios/song1.mp3"), autoStart:true, showNotification:true,);
dependencies:assets_audio_player:^3.0.8
Works withflutter: ">=3.3.0"
, be sure to upgrade your sdk
You like the package ? buy me a kofi :)
Audio Source | Android | iOS | Web | MacOS |
---|---|---|---|---|
🗄️ Asset file (asset path) | ✅ | ✅ | ✅ | ✅ |
🌐 Network file (url) | ✅ | ✅ | ✅ | ✅ |
📁 Local file (path) | ✅ | ✅ | ✅ | ✅ |
📻 Network LiveStream / radio (url) (Default, HLS, Dash, SmoothStream) | ✅ | ✅ | ✅ | ✅ |
Feature | Android | iOS | Web | MacOS |
---|---|---|---|---|
🎶 Multiple players | ✅ | ✅ | ✅ | ✅ |
💽 Open Playlist | ✅ | ✅ | ✅ | ✅ |
💬System notification | ✅ | ✅ | 🚫 | 🚫 |
🎧 Bluetooth actions | ✅ | ✅ | 🚫 | 🚫 |
🔕 Respect System silent mode | ✅ | ✅ | 🚫 | 🚫 |
📞 Pause on phone call | ✅ | ✅ | 🚫 | 🚫 |
Commands | Android | iOS | Web | MacOS |
---|---|---|---|---|
▶ Play | ✅ | ✅ | ✅ | ✅ |
⏸ Pause | ✅ | ✅ | ✅ | ✅ |
⏹ Stop | ✅ | ✅ | ✅ | ✅ |
⏩ Seek(position) | ✅ | ✅ | ✅ | ✅ |
⏪⏩ SeekBy(position) | ✅ | ✅ | ✅ | ✅ |
⏩ Forward(speed) | ✅ | ✅ | ✅ | ✅ |
⏪ Rewind(speed) | ✅ | ✅ | ✅ | ✅ |
⏭ Next | ✅ | ✅ | ✅ | ✅ |
⏮ Prev | ✅ | ✅ | ✅ | ✅ |
Widgets | Android | iOS | Web | MacOS |
---|---|---|---|---|
🐦 Audio Widget | ✅ | ✅ | ✅ | ✅ |
🐦 Widget Builders | ✅ | ✅ | ✅ | ✅ |
🐦 AudioPlayer Builders Extension | ✅ | ✅ | ✅ | ✅ |
Properties | Android | iOS | Web | MacOS |
---|---|---|---|---|
🔁 Loop | ✅ | ✅ | ✅ | ✅ |
🔀 Shuffle | ✅ | ✅ | ✅ | ✅ |
🔊 get/set Volume | ✅ | ✅ | ✅ | ✅ |
⏩ get/set Play Speed | ✅ | ✅ | ✅ | ✅ |
⏩ get/set Pitch | ✅ | 🚫 | 🚫 | 🚫 |
Listeners | Android | iOS | Web | MacOS |
---|---|---|---|---|
🦻 Listener onReady(completeDuration) | ✅ | ✅ | ✅ | ✅ |
🦻 Listener currentPosition | ✅ | ✅ | ✅ | ✅ |
🦻 Listener finished | ✅ | ✅ | ✅ | ✅ |
🦻 Listener buffering | ✅ | ✅ | ✅ | ✅ |
🦻 Listener volume | ✅ | ✅ | ✅ | ✅ |
🦻Listener Play Speed | ✅ | ✅ | ✅ | ✅ |
🦻Listener Pitch | ✅ | 🚫 | 🚫 | 🚫 |
No needed to copy songs to a media cache, with assets_audio_player you can open them directly from the assets.
- Create an audio directory in your assets (not necessary named "audios")
- Declare it inside your pubspec.yaml
flutter:assets: -assets/audios/
final assetsAudioPlayer=AssetsAudioPlayer();assetsAudioPlayer.open(Audio("assets/audios/song1.mp3"),);
You can also playnetwork songs fromurl
final assetsAudioPlayer=AssetsAudioPlayer();try {await assetsAudioPlayer.open(Audio.network("http://www.mysite.com/myMp3file.mp3"), );}catch (t) {//mp3 unreachable}
LiveStream / Radio fromurl
The main difference with network, if you pause/play, on livestream it will resume to present duration
final assetsAudioPlayer=AssetsAudioPlayer();try {await assetsAudioPlayer.open(Audio.liveStream(MY_LIVESTREAM_URL), );}catch (t) {//stream unreachable}
And playsongs from file
//create a new playerfinal assetsAudioPlayer=AssetsAudioPlayer();assetsAudioPlayer.open(Audio.file(FILE_URI),);
for file uri, please look athttps://pub.dev/packages/path_provider
assetsAudioPlayer.playOrPause();assetsAudioPlayer.play();assetsAudioPlayer.pause();
assetsAudioPlayer.seek(Duration to);assetsAudioPlayer.seekBy(Duration by);
assetsAudioPlayer.forwardRewind(double speed);//if positive, forward, if negative, rewind
assetsAudioPlayer.stop();
on iOS, it will useMPNowPlayingInfoCenter
- Add metas inside your audio
final audio=Audio.network("/assets/audio/country.mp3", metas:Metas( title:"Country", artist:"Florent Champigny", album:"CountryAlbum", image:MetasImage.asset("assets/images/country.jpg"),//can be MetasImage.network ), );
- open with
showNotification: true
_player.open(audio, showNotification:true)
Custom icon (android only)
Make sure you added those icons inside yourandroid/res/drawable
!!! not on flutter assets !!!!
await _assetsAudioPlayer.open( myAudio, showNotification:true, notificationSettings:NotificationSettings( customStopIcon:AndroidResDrawable(name:"ic_stop_custom"), customPauseIcon:AndroidResDrawable(name:"ic_pause_custom"), customPlayIcon:AndroidResDrawable(name:"ic_play_custom"), customPrevIcon:AndroidResDrawable(name:"ic_prev_custom"), customNextIcon:AndroidResDrawable(name:"ic_next_custom"), )
And don't forget tell proguard to keep those resources for release mode
(part Keeping Resources)
https://sites.google.com/a/android.com/tools/tech-docs/new-build-system/resource-shrinking
<?xml version="1.0" encoding="utf-8"?><resourcesxmlns:tools="http://schemas.android.com/tools"tools:keep="@drawable/ic_next_custom, @drawable/ic_prev_custom, @drawable/ic_pause_custom, @drawable/ic_play_custom, @drawable/ic_stop_custom"/>
Add your icon into your android's
res
folder (android/app/src/main/res)Reference this icon into your AndroidManifest (android/app/src/main/AndroidManifest.xml)
<meta-dataandroid:name="assets.audio.player.notification.icon"android:resource="@drawable/ic_music_custom"/>
You can also change actions icons
<meta-data android:name="assets.audio.player.notification.icon.play" android:resource="@drawable/ic_play_custom"/><meta-data android:name="assets.audio.player.notification.icon.pause" android:resource="@drawable/ic_pause_custom"/><meta-data android:name="assets.audio.player.notification.icon.stop" android:resource="@drawable/ic_stop_custom"/><meta-data android:name="assets.audio.player.notification.icon.next" android:resource="@drawable/ic_next_custom"/><meta-data android:name="assets.audio.player.notification.icon.prev" android:resource="@drawable/ic_prev_custom"/>
Add in main
AssetsAudioPlayer.setupNotificationsOpenAction((notification) {//custom actionreturntrue;//true : handled, does not notify others listeners//false : enable others listeners to handle it});
Then if you want a custom action on widget
AssetsAudioPlayer.addNotificationOpenAction((notification) {//custom actionreturnfalse;//true : handled, does not notify others listeners//false : enable others listeners to handle it});
You can enable/disable a notification action
open(AUDIO, showNotification:true, notificationSettings:NotificationSettings( prevEnabled:false,//disable the previous button//and have a custom next action (will disable the default action) customNextAction: (player) {print("next"); } ))
After your audio creation, just call
audio.updateMetas( player: _assetsAudioPlayer,//add the player if the audio is actually played title:"My new title", artist:"My new artist",//if I not provide a new album, it keep the old one image:MetasImage.network(//my new image url ),);
You have to enable notification to make them work
Available remote commands :
- Play / Pause
- Next
- Prev
- Stop
(Only for Android for now)
while opening a song/playlist, add a strategy
assetsAudioPlayer.open( ... headPhoneStrategy:HeadPhoneStrategy.pauseOnUnplug,//headPhoneStrategy: HeadPhoneStrategy.none, //default//headPhoneStrategy: HeadPhoneStrategy.pauseOnUnplugPlayOnPlug,)
If you want to make it work on bluetooth too, you'll have to add the BLUETOOTH permission inside your AndroidManifest.xml
<uses-permissionandroid:name="android.permission.BLUETOOTH" />
You can create new AssetsAudioPlayer using AssetsAudioPlayer.newPlayer(),which will play songs in a different native Media Player
This will enable to play two songs simultaneously
You can have as many player as you want !
///play 3 songs in parallelAssetsAudioPlayer.newPlayer().open(Audio("assets/audios/song1.mp3"));AssetsAudioPlayer.newPlayer().open(Audio("assets/audios/song2.mp3"));//another way, with create, open, play & dispose the player on finishAssetsAudioPlayer.playAndForget(Audio("assets/audios/song3.mp3"));
Each player has an unique generatedid
, you can retrieve or create them manually using
final player=AssetsAudioPlayer.withId(id:"MY_UNIQUE_ID");
assetsAudioPlayer.open(Playlist( audios: [Audio("assets/audios/song1.mp3"),Audio("assets/audios/song2.mp3") ] ), loopMode:LoopMode.playlist//loop the full playlist);assetsAudioPlayer.next();assetsAudioPlayer.prev();assetsAudioPlayer.playlistPlayAtIndex(1);
If you want a more flutter way to play audio, try theAudioWidget
!
//inside a stateful widgetbool _play=false;@overrideWidgetbuild(BuildContext context) {returnAudioWidget.assets( path:"assets/audios/country.mp3", play: _play, child:RaisedButton( child:Text( _play?"pause":"play", ), onPressed: () {setState(() { _play=!_play; }); } ), onReadyToPlay: (duration) {//onReadyToPlay }, onPositionChanged: (current, duration) {//onPositionChanged }, );}
How to 🛑 stop 🛑 the AudioWidget ?
Just remove the Audio from the tree !Or simply keepplay: false
All listeners exposes StreamsUsing RxDart, AssetsAudioPlayer exposes some listeners as ValueObservable (Observable that provides synchronous access to the last emitted item);
//The current playing audio, filled with the total song durationassetsAudioPlayer.current//ValueObservable<PlayingAudio>//Retrieve directly the current played assetfinalPlayingAudio playing= assetsAudioPlayer.current.value;//Listen to the current playing songassetsAudioPlayer.current.listen((playingAudio){final asset= playingAudio.assetAudio;final songDuration= playingAudio.duration;})
//Listen to the current playing songfinal duration= assetsAudioPlayer.current.value.duration;
assetsAudioPlayer.currentPosition//ValueObservable<Duration>//retrieve directly the current song positionfinalDuration position= assetsAudioPlayer.currentPosition.value;returnStreamBuilder( stream: assetsAudioPlayer.currentPosition, builder: (context, asyncSnapshot) {finalDuration duration= asyncSnapshot.data;returnText(duration.toString()); }),
or use a PlayerBuilder !
PlayerBuilder.currentPosition( player: _assetsAudioPlayer, builder: (context, duration) {returnText(duration.toString()); })
or Player Builder Extension
_assetsAudioPlayer.builderCurrentPosition( builder: (context, duration) {returnText(duration.toString()); })
boolean observable representing the current mediaplayer playing state
assetsAudioPlayer.isPlaying// ValueObservable<bool>//retrieve directly the current player statefinalbool playing= assetsAudioPlayer.isPlaying.value;//will follow the AssetsAudioPlayer playing statereturnStreamBuilder( stream: assetsAudioPlayer.isPlaying, builder: (context, asyncSnapshot) {finalbool isPlaying= asyncSnapshot.data;returnText(isPlaying?"Pause":"Play"); }),
or use a PlayerBuilder !
PlayerBuilder.isPlaying( player: _assetsAudioPlayer, builder: (context, isPlaying) {returnText(isPlaying?"Pause":"Play"); })
or Player Builder Extension
_assetsAudioPlayer.builderIsPlaying( builder: (context, isPlaying) {returnText(isPlaying?"Pause":"Play"); })
Change the volume (between 0.0 & 1.0)
assetsAudioPlayer.setVolume(0.5);
The media player can follow the system "volume mode" (vibrate, muted, normal)Simply set therespectSilentMode
optional parameter astrue
_player.open(PLAYABLE, respectSilentMode:true);
https://developer.android.com/reference/android/media/AudioManager.html?hl=fr#getRingerMode()
https://developer.apple.com/documentation/avfoundation/avaudiosessioncategorysoloambient
Listen the volume
returnStreamBuilder( stream: assetsAudioPlayer.volume, builder: (context, asyncSnapshot) {finaldouble volume= asyncSnapshot.data;returnText("volume : $volume"); }),
or use a PlayerBuilder !
PlayerBuilder.volume( player: _assetsAudioPlayer, builder: (context, volume) {returnText("volume : $volume"); })
Called when the current song has finished to play,
it gives the Playing audio that just finished
assetsAudioPlayer.playlistAudioFinished//ValueObservable<Playing>assetsAudioPlayer.playlistAudioFinished.listen((Playing playing){})
Called when the complete playlist has finished to play
assetsAudioPlayer.playlistFinished//ValueObservable<bool>assetsAudioPlayer.playlistFinished.listen((finished){})
finalLoopMode loopMode= assetsAudioPlayer.loop;// possible values// LoopMode.none : not looping// LoopMode.single : looping a single audio// LoopMode.playlist : looping the fyll playlistassetsAudioPlayer.setLoopMode(LoopMode.single);assetsAudioPlayer.loopMode.listen((loopMode){//listen to loop})assetsAudioPlayer.toggleLoop();//toggle the value of looping
assetsAudioPlayer.setPlaySpeed(1.5);assetsAudioPlayer.playSpeed.listen((playSpeed){//listen to playSpeed})//change play speed for a particular AudioAudio audio=Audio.network( url, playSpeed:1.5);assetsAudioPlayer.open(audio);
assetsAudioPlayer.setPitch(1.2);assetsAudioPlayer.pitch.listen((pitch){//listen to pitch})//change pitch for a particular AudioAudio audio=Audio.network( url, pitch:1.2);assetsAudioPlayer.open(audio);
By default, on playing error, it stop the audio
BUT you can add a custom behavior
_player.onErrorDo= (handler){ handler.player.stop();};
Open another audio
_player.onErrorDo= (handler){ handler.player.open(ANOTHER_AUDIO);};
Try to open again on same position
_player.onErrorDo= (handler){ handler.player.open( handler.playlist.copyWith( startIndex: handler.playlistIndex ), seek: handler.currentPosition );};
Android only allow HTTPS calls, you will have an error if you're using HTTP,don't forget to add INTERNET permission and seetusesCleartextTraffic="true"
in yourAndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest ...> <uses-permission android:name="android.permission.INTERNET" /> <application ... android:usesCleartextTraffic="true" ...> ... </application></manifest>
iOS only allow HTTPS calls, you will have an error if you're using HTTP,don't forget to edit yourinfo.plist and setNSAppTransportSecurity
toNSAllowsArbitraryLoads
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsArbitraryLoads</key> <true/></dict>
To enable http calls on macOs, you have to add input/output calls capabilities intoinfo.plist
<key>NSAppTransportSecurity</key><dict> <key>NSAllowsArbitraryLoads</key> <true/></dict><key>UIBackgroundModes</key><array> <string>audio</string> <string>fetch</string></array><key>com.apple.security.network.client</key><true/>
and in your
Runner/DebugProfile.entitlements
add
<key>com.apple.security.network.client</key><true/>
CompleteRunner/DebugProfile.entitlements
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>com.apple.security.app-sandbox</key><true/><key>com.apple.security.cs.allow-jit</key><true/><key>com.apple.security.network.server</key><true/><key>com.apple.security.network.client</key><true/></dict></plist>
All musics used in the samples came fromhttps://www.freemusicarchive.org/
About
Play simultaneously music/audio from assets/network/file directly from Flutter, compatible with android / ios / web / macos, displays notifications
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.