Flutter Assets Audio Player, A Guideline to Build an Audio Player Selecting Files From ‘assets’ Directory

Nahid Ibne Akhtar
5 min readSep 25, 2020

Introductory guide for flutter’s audioplayers library to create a local assets directory audio player and how to deal with multiple mp3 files in the directory.

The things we are going to learn from this article is -

  1. How to use Flutter’s built-in media functions to play audio files.
  2. How to retrieve files from assets directory in list format.
  3. How to present the retrived file list to ListView format and implement select method to play a certain mp3 file.
  4. How to implement play, pause and stop functionality over a mp3 file.
  5. How to implement a slider to track the current position of playing.
Demo module of the audio player

Now, Let’s begin to build this simple application step by step. After building this simple project, hopefully, we will have a clear understanding of the context of the article.

STEP. 1: Adding the packages to the pubspec.yml file and create the file directory

Add ‘audioplayers’ package under the dependencies. Use the current version of the package.

dependencies:
flutter:
sdk: flutter
audioplayers: ^0.16.1

Remove the comment sign from the assets tag in the pubspec.yml file and declare the file directory under it, shown in below. You have to do it carefully as without proper indentation, it may return error.

assets:
- assets/

Then Create a directory named ‘assets’ under the root directory of the project. Paste some mp3 files inside this directories. As you can see my project name is ‘experimental_local_audio’, aaah,,,We always struggle to give a proper name for our projects,,:V,,,,and I created the ‘assets’ directory under it.

project file structure

STEP. 2: Import the Packages

The following packages have to be impoted in your Dart file-

import 'dart:convert';
import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

STEP. 3: Initialize the variables You will be needing

Globally declare two list variables like this

List<String> value;
List<String> files;

Create a stateful widget and Inside the ‘class _“Your stateful widget name” extends’ State<LocalPlayer>’ part of the widget declare the following variables-

List newTaskTitle;
String path;
Duration _duration = new Duration();
Duration _position = new Duration();
AudioPlayer audioPlayer;
AudioCache audioCache;

STEP. 4: File paths retriving from the assets directory as list format

To play the mp3 files we need to get the paths of the file thus the mediaplayer can read that directory and play the selected mp3 file. So, we have implemented a function named ‘_initFiles’ can read the file paths what is in json format, decode it in String and return a list named ‘files’ containing the file paths. We have taken only the mp3 files here, You can try other formats of audio also.

_initFiles() async {
String manifestContent = await rootBundle.loadString('AssetManifest.json');

final Map<String, dynamic> manifestMap = json.decode(manifestContent);
// >> To get paths you need these 2 lines

final filePaths = manifestMap.keys
.where((String key) => key.contains('assets/'))
.where((String key) => key.contains('.mp3'))
.toList();
files = filePaths;
return files;
}

STEP. 5: Initialize the audio player’s property

Here we have initialized the primary state of the audio player and the slider of the audio player. We have created an Audioplayer object that will help us to play the selected audio and object of AudioCache will help us to have control over the playing audio.

@override
void initState(){
super.initState();
initPlayer();
}

void initPlayer(){
audioplayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: audioplayer);

audioPlayer.durationHandler = (d) => setState(() {
_duration = d;
});

audioPlayer.positionHandler = (p) => setState(() {
_position = p;
});
}

STEP. 6: Create a functional slider for the audio that will be playing

to create a slider we have created a slider widget that initialize and calibrate the slider parameters. The ‘seekToSecond’ function calibrate the duration and time of the slider in seconds. The other widgets adds the graphical property to the slider.

//Slider Widget
Widget slider() {
return Slider(
value: _position.inSeconds.toDouble(),
min: 0.0,
max: _duration.inSeconds.toDouble(),
onChanged: (double value) {
setState(() {
seekToSecond(value.toInt());
value = value;
});});
}

//Seek Seconds
void seekToSecond(int second){
Duration newDuration = Duration(seconds: second);
audioPlayer.seek(newDuration);
}

// Tab For the player is here
Widget _tab(List<Widget> children) {
return Center(
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: children
.map((w) => Container(child: w, padding: EdgeInsets.all(6.0)))
.toList(),
),
),
);
}

//Local Asset widget
Widget localAsset() {
return _tab([
Text('The Slider.....'),
slider()
]);
}

STEP. 7: Create Play, Pause and Stop function

The play, pause and stop functions are created to add these functionality to the player. For playing we have used AudioCache and for pause and stop we have used AudioPlayer’s object.

//Audio Play Function
playAudio(String track){
return audioCache.play(track);
}

//Audio pause Function
pauseAudio(){
return audioPlayer.pause();
}

//Audio Stop Function
stopAudio(){
return audioPlayer.stop();
}

STEP. 8: Calling all the functions and widgets in the User Interface, implementation of the ListView and selection process of a certain audio file for playing

In this section the list of the files are presented in a listview and every items of the list has a onTap property what returns the index of the list that has been used to select the audio track and pass it to the player function to play the audio. The pause and stop button activate the pause and stop function to run the processes.

Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal[100],
appBar: AppBar(
title: Text('local player'),
),
body: Column(
children: [
FlatButton(
child: Text('press'),
onPressed: () async{
value = await _initFiles();
print(value);
setState(() {
newTaskTitle = value;
});
},
),
Expanded(
child: value == null ? SingleChildScrollView(child: Container()) : Padding(
padding: const EdgeInsets.all(10.0),
child: new ListView.builder(
itemCount: newTaskTitle.length,
itemBuilder: (BuildContext context, int position) {
return Card(
child: new ListTile(
title: new Text('${newTaskTitle[position]}'),
onTap: () {
//Call Audio Play Function
var trt = newTaskTitle[position].split('/');
path = trt[1].toString();
},
),
);
}),
),
),
localAsset(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, //Center Row contents vertically
children: [
IconButton(
icon: Icon(
Icons.play_arrow,
),
iconSize: 40,
color: Colors.blueAccent,
onPressed: (){
playAudio(path);
},
),
SizedBox(width: 30.0,),
IconButton(
icon: Icon(
Icons.pause,
),
iconSize: 40,
color: Colors.blueAccent,
onPressed: (){
pauseAudio();
},
),
SizedBox(width: 30.0,),
IconButton(
icon: Icon(
Icons.stop,
),
iconSize: 40,
color: Colors.blueAccent,
onPressed: (){
stopAudio();
},
),

],
)
],
),
);
}
}

Github Link of the project is here

--

--