making my flutter music player play in background

1.7k views Asked by At

i am fairly new in flutter and i am trying to make a music player app. the app works fine and all but the problem is it doesnot play in background/lockscreen. i went through some docs and it says to use audio_service package for that but i am currently using flutter_audio_query package...all the docs i went through shows a solution which results in entirely changing the code... so my question is ...is there any way to make the app play in background without changing the code entirely?

heres what my code looks like

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_audio_query/flutter_audio_query.dart';
import 'package:just_audio/just_audio.dart';

class MusicPlayer extends StatefulWidget {
  SongInfo songInfo;
  Function changeTrack;
  final GlobalKey<MusicPlayerState> key;
  MusicPlayer({required this.songInfo, required this.changeTrack, required this.key}):super(key: key);

  @override
  MusicPlayerState createState() => MusicPlayerState();
}

class MusicPlayerState extends State<MusicPlayer> {
  double minimumValue = 0.0, maximumValue = 0.0, currentValue = 0.0;
  String currentTime = '', endTime = '';
  bool isPlaying = false;

  final AudioPlayer player = AudioPlayer();

  void initState() {
    super.initState();
    setSong(widget.songInfo);
  }

  void dispose(){
    super.dispose();
    player?.dispose();
  }

  void setSong(SongInfo songInfo) async {
    widget.songInfo = songInfo;
    await player.setUrl(widget.songInfo.uri);
    currentValue = minimumValue;
    maximumValue = player.duration!.inMilliseconds.toDouble();
    setState(() {
      currentTime = getDuration(currentValue);
      endTime = getDuration(maximumValue);
    });
    isPlaying=false;
    changeStatus();
    player.positionStream.listen((duration) {
      currentValue=duration.inMilliseconds.toDouble();
      setState((){
        currentTime=getDuration(currentValue);
      });
    });
  }

  void changeStatus(){
    setState((){
      isPlaying=!isPlaying;

    });
    if(isPlaying){
      player.play();
    }else{
      player.pause();
    }
  }


  String getDuration(double value) {
    Duration duration = Duration(milliseconds: value.round());
    return [duration.inMinutes, duration.inSeconds]
        .map((e) => e.remainder(60).toString().padLeft(2, '0'))
        .join(':');
  }

  Widget build(context) {
    return Scaffold(
      backgroundColor: Colors.black38,
      appBar: AppBar(
        backgroundColor: Colors.black,
        leading: IconButton(
          onPressed: () {
            Navigator.of(context).pop();
          },
          icon: Icon(
            Icons.arrow_back,
            color: Colors.white,
          ),
        ),
        title: const Text(
          'Now Playing',
          style: TextStyle(color: Colors.white),
        ),
      ),
      body: Container(
        margin: EdgeInsets.fromLTRB(15, 50, 5, 0),
        child: Column(
          children: <Widget>[
            CircleAvatar(
              backgroundImage: widget.songInfo.albumArtwork == null
                  ? AssetImage('assets/images/album_image.jpg')
                  : FileImage(
                      File(widget.songInfo.albumArtwork),
                    ) as ImageProvider,
              radius: 95,
            ),
            Container(
              color: Colors.black,
              margin: EdgeInsets.fromLTRB(0, 10, 0, 7),
              child: Text(
                widget.songInfo.title,
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 16,
                    fontWeight: FontWeight.w600),
              ),
            ),
            Container(
              color: Colors.black,
              margin: EdgeInsets.fromLTRB(0, 0, 0, 15),
              child: Text(
                widget.songInfo.artist,
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 12,
                    fontWeight: FontWeight.w500),
              ),
            ),
            Slider(
              value: currentValue,
              min: minimumValue,
              max: maximumValue,
              onChanged: (value) {
                currentValue = value;
                player.seek(Duration(milliseconds: currentValue.round()));
              },
              inactiveColor: Colors.grey,
              activeColor: Colors.green,
            ),
            Container(
              transform: Matrix4.translationValues(0, -5, 0),
              margin: EdgeInsets.fromLTRB(5, 0, 5, 15),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    currentTime,
                    style: TextStyle(
                        color: Colors.white,
                        fontSize: 12,
                        fontWeight: FontWeight.w500),
                  ),
                  Text(
                    endTime,
                    style: TextStyle(
                        color: Colors.white,
                        fontSize: 12,
                        fontWeight: FontWeight.w500),
                  ),
                ],
              ),
            ),
            Container(
              margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  GestureDetector(
                    child: Icon(Icons.skip_previous,
                        color: Colors.white, size: 55,),
                    behavior: HitTestBehavior.translucent,
                    onTap: () {
                      widget.changeTrack(false);
                    },
                  ),
                  GestureDetector(
                    child: Icon(isPlaying?Icons.pause:Icons.play_arrow,
                        color: Colors.white, size: 75,),
                    behavior: HitTestBehavior.translucent,
                    onTap: () {
                      changeStatus();
                    },
                  ),
                  GestureDetector(
                    child: Icon(Icons.skip_next,
                        color: Colors.white, size: 55,),
                    behavior: HitTestBehavior.translucent,
                    onTap: () {
                      widget.changeTrack(true);
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

appreciate any help that i can get...thank you

2

There are 2 answers

0
Chris Pi On

The description of "flutter_audio_query" says clearly that it is no audio player. It is a library to fetch music albums and covers.

"audio_service" on the other hand says clearly that it is for playing audio.

I would suggest to start again if you won't cause problems which could be avoided

1
Rana sharjeel Ali On

Use the dependency assets_audio_player. it has a built-in function for this no need to even code. there is a little one-screen player for you. Just copy paste the code below and must add all the dependencies. Music will be played in background, on notification bar and on lock screen.

    import 'dart:convert';
    
    import 'package:assets_audio_player/assets_audio_player.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:musiccontrol/MusicPlayerModel.dart';
    
    class Home extends StatefulWidget {
      Home({
        super.key,
        t,
      });
      MusicPlaylist? _musicPlaylist;
      @override
      State<Home> createState() => _HomeState();
    }
    
    class _HomeState extends State<Home> {
      List SongsList = [];
      bool MuteVolume = false;
    
    // Fetch content from the json file
    
      final AssetsAudioPlayer audioplayer = AssetsAudioPlayer();
      double screenwidth = 0;
      double screenheight = 0;
    
      @override
      void initState() {
        super.initState();
        setupPlaylist();
      }
    
    // songs paths and links
      void setupPlaylist() async {
        await audioplayer.open(
          showNotification: true,
          Playlist(audios: [
            // Audio(SongsList[2].,
            //     metas: Metas(
            //       title: "Bazz01",
            //       artist: 'Talha',
            //     )),
            Audio.network(
              'https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview125/v4/09/17/bb/0917bbe1-58c3-6252-d00e-9b70d42ef5dc/mzaf_2269500085377778268.plus.aac.p.m4a',
              metas: Metas(
                id: 'Online',
                title: 'Online',
                artist: 'Florent Champigny',
                album: 'OnlineAlbum',
    
                // image: MetasImage.network('https://www.google.com')
                image: const MetasImage.network(
                    'https://i.dawn.com/large/2021/09/61399fb500900.png'),
              ),
            ),
         Audio.network(
              'https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview125/v4/09/17/bb/0917bbe1-58c3-6252-d00e-9b70d42ef5dc/mzaf_2269500085377778268.plus.aac.p.m4a',
              metas: Metas(
                id: 'Online',
                title: 'Online',
                artist: 'Florent Champigny',
                album: 'OnlineAlbum',
    
                // image: MetasImage.network('https://www.google.com')
                image: const MetasImage.network(
                    'https://i.dawn.com/large/2021/09/61399fb500900.png'),
              ),
            ),
          ]),
          autoStart: true,
          loopMode: LoopMode.playlist,
        );
      }
      var forward= AssetImage('assets/forward.png');
    
      @override
      void dispose() {
        super.dispose();
        setupPlaylist();
      }
    
      Widget slider(RealtimePlayingInfos realtimePlayingInfos) {
        return SliderTheme(
            data: const SliderThemeData(
              thumbShape: RoundSliderThumbShape(enabledThumbRadius: 8),
            ),
            child: Slider.adaptive(
                activeColor: const Color.fromARGB(255, 241, 241, 241),
                inactiveColor: const Color.fromARGB(255, 219, 217, 217),
                thumbColor: const Color.fromARGB(255, 255, 255, 255),
                value: realtimePlayingInfos.currentPosition.inSeconds.toDouble(),
                max: realtimePlayingInfos.duration.inSeconds.toDouble(),
                onChanged: (value) {
                  audioplayer.seek(Duration(seconds: value.toInt()));
                }));
      }
    
      Widget timeStamps(RealtimePlayingInfos realtimePlayingInfos) {
        return Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(
              transformString(realtimePlayingInfos.currentPosition.inSeconds),
              style: const TextStyle(color: Colors.white),
            ),
            Text(transformString(realtimePlayingInfos.duration.inSeconds),
                style: const TextStyle(color: Colors.white)),
          ],
        );
      }
      // slider timings
    
      String transformString(int seconds) {
        String minuteString =
            '${(seconds / 60).floor() < 10 ? 0 : ''}${(seconds / 60).floor()}';
        String secondString = '${seconds % 60 < 10 ? 0 : ' '}${seconds % 60}';
        return '$minuteString:$secondString';
      }
    
      //control buttons of music player
      Widget playBar(RealtimePlayingInfos realtimePlayingInfos) {
        return SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Icon_Button(
                  icon: Icons.compare_arrows_rounded,
                  size: 21,
                  passedfunc: () {
                    audioplayer.toggleShuffle();
                  }),
              Icon_Button(
                  icon: Icons.fast_rewind_rounded,
                  size: 21,
                  passedfunc: () {
                    audioplayer.seekBy(const Duration(seconds: -15));
                  }),
              Icon_Button(
                  icon: Icons.skip_previous_rounded,
                  size: 21,
                  passedfunc: () => audioplayer.previous()),
              Icon_Button(
                  icon: realtimePlayingInfos.isPlaying
                      ? Icons.pause_circle_filled_rounded
                      : Icons.play_circle_fill_rounded,
                  size: 50,
                  passedfunc: () => audioplayer.playOrPause()),
              Icon_Button(
                  icon: Icons.skip_next_rounded,
                  size: 21,
                  passedfunc: () => audioplayer.next()),
              Icon_Button(
                  icon: Icons.fast_forward_rounded, 
                  size: 21,
                  passedfunc: () {
                    setState(() {
                      audioplayer.seekBy(const Duration(seconds: 15));
                    });
                  }),
              Icon_Button(
                icon: MuteVolume == true
                    ? Icons.volume_off_outlined
                    : Icons.volume_up,
                size: 21,
                passedfunc: () {
                  if (MuteVolume == true) {
                    setState(() {
                      audioplayer.setVolume(1);
                      MuteVolume = !MuteVolume;
                    });
                  } else {
                    audioplayer.setVolume(0);
                    MuteVolume = !MuteVolume;
                  }
                },
              ),
            ],
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        // screenheight = MediaQuery.of(context).size.height;
        // screenwidth = MediaQuery.of(context).size.width;
    
        return Scaffold(
          backgroundColor: const Color.fromARGB(31, 142, 111, 253),
          body: audioplayer.builderRealtimePlayingInfos(
              builder: (context, realtimePlayingInfos) {
            // ignore: unnecessary_null_comparison
            if (realtimePlayingInfos != null) {
              return Column(
                //Designing Texts and image
                children: [
                  Padding(
                    padding: const EdgeInsets.all(23.0),
                    child: Row(
                      children: [
                        ClipRRect(
                            borderRadius: BorderRadius.circular(40),
                            child: Image.network(
                              'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUyCn1ItXdchQzeH8MkPEtQJcKttTplAw7oDrBuQI&s',
                              height: 70,
                              width: 70,
                            )),
                        Padding(
                          padding: const EdgeInsets.all(12.0),
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.start,
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              const Text(
                                'Sound Cloud',
                                style: TextStyle(color: Colors.white, fontSize: 18),
                              ),
                              const Text(
                                'Name Goes',
                                style: TextStyle(color: Colors.white, fontSize: 15),
                              ),
                              const Text(
                                'Song Name Goes here',
                                style: TextStyle(color: Colors.white, fontSize: 20),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                  // slider code is here
                  Stack(
                    children: [
                      Column(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: [
                          slider(realtimePlayingInfos),
                          SizedBox(
                            height: screenheight * 0.05,
                          ),
                          timeStamps(realtimePlayingInfos),
                          SizedBox(
                            height: screenheight * 0.05,
                          ),
                          playBar(realtimePlayingInfos),
                        ],
                      )
                    ],
                  ),
                ],
              );
            } else {
              return Column();
            }
          }),
        );
      }
    }
    
    // Icon_Button custom widget
    
    // ignore: camel_case_types, must_be_immutable
    class Icon_Button extends StatelessWidget {
      Icon_Button(
          {super.key,
          required this.icon,
          required this.size,
          required this.passedfunc});
    
      IconData icon;
      double size;
      final passedfunc;
      @override
      Widget build(BuildContext context) {
        return IconButton(
          onPressed: passedfunc,
          icon: Icon(icon),
          iconSize: size,
          color: Colors.grey,
          splashColor: Colors.transparent,
          highlightColor: Colors.transparent,
        );
      }
    }