Flutter in Android - AudioPlayers package : MediaPlayerNative(21219): stop called in state 1, mPlayer(0x0), error (-38, 0)

Viewed 17

I need to play sound once a widget is rendered and then stop it once it is disposed. I have the following code but the behavior is weird. Sometimes it plays just fine. sometimes it plays once and does not loop. Sometime it does not play at all.
I am testing on an actual android device. In the terminal, I get this:

E/MediaPlayerNative(21219): stop called in state 1, mPlayer(0x0)
E/MediaPlayerNative(21219): error (-38, 0)
V/MediaPlayer(21219): resetDrmState:  mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
V/MediaPlayer(21219): cleanDrmObj: mDrmObj=null mDrmSessionId=null
V/MediaPlayer(21219): resetDrmState:  mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
V/MediaPlayer(21219): cleanDrmObj: mDrmObj=null mDrmSessionId=null

Widget:

class TopButtonBackground extends StatefulWidget {
  const TopButtonBackground({
    Key? key,
  }) : super(key: key);

  @override
  State<TopButtonBackground> createState() => _TopButtonBackgroundState();
}

class _TopButtonBackgroundState extends State<TopButtonBackground>
    with SingleTickerProviderStateMixin {
  Animation<double>? _animation;
  AnimationController? _controller;
  AudioPlayer player = AudioPlayer();
  static AudioCache audioCache = AudioCache(prefix: 'assets/');
  @override
  void initState() {
    super.initState();
    _playAudio();
    _controller =
        AnimationController(duration: const Duration(seconds: 12), vsync: this);
    _animation = Tween<double>(begin: 0, end: 1).animate(_controller!)
      ..addListener(() {
        setState(() {});
      });
    _controller?.forward();
  }

  void _playAudio() async {
    final url = await audioCache.load("direct_request_tune.mp3");
    player.setReleaseMode(ReleaseMode.loop);
    player.play(DeviceFileSource(url.path));
  }

  @override
  void dispose() {
    _controller?.dispose();
    player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (_animation != null) {
      return Opacity(
        opacity: min((sin(_animation!.value * 50) + 1.3) / 2, 1),
        child: Container(
            height: 70,
            width: MediaQuery.of(context).size.width * _animation!.value,
            color: Colors.grey.withOpacity(.2)),
      );
    }
    return Container(height: 70);
  }
}

What is the reason of this unpredictable behavior?

1 Answers

I think I discovered the issue. player.setRleaseMode(ReleaseMode.loop) is async. I need to wait for it.

await player.setReleaseMode(ReleaseMode.loop);
Related