Playing Audio From the Web and HTTP

Goal of this Tutorial

The goal of this tutorial is to see how easy it is to use plugins with flutter as well as how easy it is to make HTTP calls over the web.  When we are done you’ll have learned how to add a plugin and how to play an audio file that was downloaded from the web.

Our Plugin

To play audio files, we are going to give audioplayer 0.3.0 a whirl.

Our HTTP Library

To make http calls, we will be using the http dart library.

Creating the App

If you are not yet familiar with the basics of creating a flutter app, please see my first post in this series on flutter – From Zero to App with Flutter.

Note – for this post we’ll be using VS Code although other IDEs may be used.  Open up VS Code and from the command palette (CTRL+SHIFT+P) choose ‘Flutter:New Project’.  Enter a new project name and hit Enter.  VS Code will setup your new project, which we will be heavily modifying next…

Adding Dependencies

Open up your pubspec.yaml file and edit the dependencies section so that it appears as follows:


dependencies:
  flutter:
    sdk: flutter
  audioplayer: "^0.3.0"
  path_provider: "^0.3.1"

Warning – if you are not familiar with yaml, be aware that indentation is important so follow the example above closely.

The audioplayer dependency was mentioned earlier and is what we will be using to play audio files.  The other dependency, path_provider, allows us easy access to common folders on a device.  We will take advantage of this in order to store an .mp3 file on the device in order to play it.

Save your pubspec.yaml file and VS Code will automagically pull down the packages for you.  Open up the output window within VS Code and you will see confirmation of this: 

Code our User Interface

Next, we will create the code for our user interface.  This is going to be simply a button centered on the screen that you can click to play the audio file.  Here is the main.dart file – you may replace your own main.dart file with this code:


import 'package:flutter/material.dart';
import 'package:audioplayer/audioplayer.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Player',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Player Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static String url =
      'https://codingwithjoe.com/wp-content/uploads/2018/03/applause.mp3';
  AudioPlayer audioPlayer = new AudioPlayer();
  AudioProvider audioProvider = new AudioProvider(url);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new RaisedButton(
              onPressed: play,
              child: new Text('Click me to Play'),
            )
          ],
        ),
      ),
    );
  }

  play() async {

  }
}

Downloading the Audio File

Go ahead and create another dart source code file and name it audio_provider.dart.  Here is the code to place in that file:


import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart';

typedef void OnError(Exception exception);

class AudioProvider {
  String url;

  AudioProvider(String url) {
    this.url = url;
  }

  Future<Uint8List> _loadFileBytes(String url, {OnError onError}) async {
    Uint8List bytes;
    try {
      bytes = await readBytes(url);
    } on ClientException {
      rethrow;
    }
    return bytes;
  }

  Future<String> load() async {
    final bytes = await _loadFileBytes(url,
        onError: (Exception exception) =>
            print('audio_provider.load => exception ${exception}'));

    final dir = await getApplicationDocumentsDirectory();
    final file = new File('${dir.path}/audio.mp3');

    await file.writeAsBytes(bytes);
    if (await file.exists()) {
      return file.path;
    }
    return '';
  }
}

The method that makes the HTTP call is _loadFileBytes.  Within this method we use the HTTP package library’s readBytes method.  ReadBytes internally creates a new Client which simplifies the code we need to write.  The other method in this class, load(), takes care of storing the downloaded audio file on the device using the getApplicationDocumentsDirectory.

Implementing Play

You probably noticed our main.dart file had a method with no impementation – play().  Let’s make two modifications to the main.dart file.  Import our audio_provider.dart at the top of the main.dart file.  Like this:

import 'package:audioplayer/audioplayer.dart';

Next, implement the play() method. Here is the enter code for the play() method:


  play() async {
    String localUrl = await audioProvider.load();
    audioPlayer.play(localUrl, isLocal: true);
  }

That’s all of the code we need.  Make sure you have a connected device or emulator working and running.  If you need a refresher on this, please visit the official flutter documentation as it details setup for both Android and iOS platforms.  Once you have verified your device is connected (remember you can use ‘flutter devices’ in a terminal window to check this).  Press F5 within VS Code to run the app.  You should see the app on your device or emulator as follows:

Click the ‘Click me to play’ button and you’ll be rewarded with the sounds of people cheering you on!

Summary

This was a fairly simple app but we did touch in a few key areas more complex apps would depend on – HTTP and the folder/file structure on the device.  There is a lot more to delve into in each area.  Use the comment section below to let me know what you would like to see next.

Leave a Reply

Your email address will not be published. Required fields are marked *