androidflutteraudio

Flutter Android disable background sound


I created a Flutter application and I am playing an audio file using the assets_audio_player: ^3.1.1 package when the app opens.
How can I disable the sound when you exit the app without close it from the running apps
I added the property playInBackground: PlayInBackground.disabledRestoreOnForeground but you have to exit the app twice for the audio to stop. Is there any property to add on AndroidManifest.xml to handle it?


Solution

  • For me it looks like a bug in the package, cause this behaviour (double-exit to stop music) is indeed weird. I've managed to reproduce it myself, so it's not only problem of your environment.

    I think, one can overcome it with manual start/stop playback based on current lifecycle state of the application. WidgetsBindingObserver can be used for this.

    It works like this (I will provide code in the end):

    1. Make sure that your widget is StatefulWidget, because you can't use those lifecycle methods on StatelessWidget.
    2. Add WidgetsBindingObserver mixin to the state of your widget.
    3. Add observer with WidgetsBinding.instance.addObserver(this); inside initState()
    4. now you have access to lifecycle methods. You will need to override didChangeAppLifecycleState(AppLifecycleState state) link and add logic to start/stop music there based on current lifecycle state. Basically, you'll need to start when state is resumed, and stop otherwise.

    Here is example code. This is totally empty app, only thing happens here is music :)

    import 'package:flutter/material.dart';
    import 'package:assets_audio_player/assets_audio_player.dart';
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
      final AssetsAudioPlayer _audioPlayer = AssetsAudioPlayer();
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
        // We have to start music in initState() since didChangeAppLifecycleState is not called when app starts for the first time :(
        _playAudio();
      }
    
      @override
      void dispose() {
        // Do not forget to release all resources here
        WidgetsBinding.instance.removeObserver(this);
        _audioPlayer.dispose();
        super.dispose();
      }
    
      void _playAudio() {
        _audioPlayer.open(
          Audio("assets/audio/country.mp3"),
          autoStart: true,
          // No need to use playInBackground: PlayInBackground.disabledRestoreOnForeground in that case, cause we rule ourselves
        );
      }
    
      @override
      void didChangeAppLifecycleState(AppLifecycleState state) {
        // Core logic is here
        if (state == AppLifecycleState.resumed) {
          _playAudio();
        } else {
          _audioPlayer.stop();
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp();
      }
    }
    
    void main() => runApp(MyApp());