ConceptorWeb
ConceptorWeb

Reputation: 31

flutter / dart: playing music when launching the application and which continues even after redirecting to another page

I am working on a small project on Flutter and Dart. I have several .dart pages in my application, and I would like an autoplay music to play at startup, and that this music continue playing even after switching to another Dart page. I am using the "audioplayers: 0.17.0" package, but I can't launch my mp3 in autoplay, and the music stops playing when I click on a link which leads to a new page.

Here is the part of the code that I was able to do about this problem:

Thanks for your help!

import 'package:audioplayers/audio_cache.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/widgets.dart';
import 'route.dart'as route ;
import 'page2.dart';

void main() {
  runApp(TinyAppli());
}

class TinyAppli extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tiny Appli',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(scaffoldBackgroundColor: const Color(0x000000),
        primarySwatch: Colors.amber,
      ),
      onGenerateRoute: route.controller,
      initialRoute: route.homePage,
      home: TinyApplication(title: 'Welcome to The Tiny Application !'),
    );
  }
}

class TinyApplication extends StatefulWidget {
  TinyApplication({Key? key, required this.title}) : super(key: key);
  
  final String title;
  
  @override
  _TinyApplicationState createState() =>
      _TinyApplicationState();
}

class _TinyApplicationState extends State<TinyApplication> {

  AudioPlayer audioPlayer = AudioPlayer();
  AudioPlayerState audioPlayerState = AudioPlayerState.PAUSED;
  
  late AudioCache audioCache;
  String path = 'music.mp3';
  
  @override
  void initState() {
    super.initState();

    audioCache = AudioCache(fixedPlayer: audioPlayer);
    audioPlayer.onPlayerStateChanged.listen((AudioPlayerState s) {
      setState(() {
        audioPlayerState = s;
      });
    });
  }
  
  @override
  void dispose() {
    super.dispose();
    audioPlayer.release();
    audioPlayer.dispose();
    audioCache.play('music.mp3');
  }
  
  playMusic() async{
    await audioCache.play(path);
  }
  
  pauseMusic() async {
    await audioPlayer.pause();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: BaseAppBar(
          title: Text('title'),
          appBar: AppBar(),
          widgets: <Widget>[musicPlay(),],
        ),
        
        body: Container(
            child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Center(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        IconButton(
                          icon: Image.asset('assets/logo_conceptorweb.jpg'),
                          iconSize: 200,
                          onPressed: () =>
                              Navigator.pushReplacement(
                                context,
                                PageRouteBuilder(
                                  pageBuilder: (context, animation1, animation2) => StartAppli(title: 'Tiny Appli',),
                                  transitionDuration: Duration.zero,
                                ),
                              ),
                        )
                      ],
                    ),
                  ),
                ]
            )
        )
    );
  }
  
  IconButton musicPlay() {
    return IconButton(
      onPressed: () {
        audioPlayerState == AudioPlayerState.PLAYING
            ? pauseMusic()
            : playMusic();
      },
      icon: Icon(audioPlayerState == AudioPlayerState.PLAYING
          ? Icons.pause_rounded
          : Icons.play_arrow_rounded
      ),
    );
  }
  
}

Upvotes: 2

Views: 1781

Answers (2)

Gk Mohammad Emon
Gk Mohammad Emon

Reputation: 6938

I made a util class for playing the music and pausing it on demand. You can modify it as per your demand.

class AudioUtils {
  static AudioCache? _bgAudioCache;
  static AudioPlayer? _bgAudioPlayer;

  static AudioCache? getBGAudioCache() {
    if (_bgAudioCache == null)
      return _bgAudioCache = AudioCache();
    else
      return _bgAudioCache;
  }

  static void playBgMusic() async {
      if (_bgAudioPlayer == null){
        _bgAudioPlayer =
        await getBGAudioCache()?.loop("bg-music.mp3", volume: 0.1);
      } else _resumeBgMusic();
  }

  static void pauseBgMusic() {
    _bgAudioPlayer?.pause();
  }

  static void _resumeBgMusic() {
    _bgAudioPlayer?.resume();
  }

  static disposeBGMusic() {
    _bgAudioPlayer?.dispose();
  }

  static bool isBGMusicPlaying() {
    return _bgAudioPlayer?.state == PlayerState.PLAYING;
  }
}

Finally, I handled the music pause and play on application lifecycle by this approach inspired from Ayar's answer above -

class _MainAppState extends State<MainApp>  with WidgetsBindingObserver {
  @override
  void initState() {
   .
   .
   .
    WidgetsBinding.instance?.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
   .
   .
   .
    WidgetsBinding.instance?.removeObserver(this);
    super.dispose();
  }


  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    switch (state) {
      case AppLifecycleState.resumed:
        print("app in resumed");
        AudioUtils.playBgMusic();
        break;
      case AppLifecycleState.inactive:
        print("app in inactive");
        AudioUtils.pauseBgMusic();//If you want to pause music while inactive. 
        break;
      case AppLifecycleState.paused:
        print("app in paused");
        AudioUtils.pauseBgMusic();
        break;
      case AppLifecycleState.detached:
        print("app in detached");
        AudioUtils.disposeBGMusic();
        break;
    }
  }
}

Make sure that _MainAppState is your master/main widget's state.

Upvotes: 1

Zeeshan Ayaz
Zeeshan Ayaz

Reputation: 1038

Extend your class with WidgetsBindingObserver and then override the lifecycle functions.

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    switch (state) {
      case AppLifecycleState.resumed:
        print("app in resumed");
        //Play the Music
        break;
      case AppLifecycleState.inactive:
        print("app in inactive");
        //Stop the music
        break;
      case AppLifecycleState.paused:
        print("app in paused");
        break;
      case AppLifecycleState.detached:
        print("app in detached");
        //Stop the music
        break;
    }
  }

Upvotes: 1

Related Questions