Skip to content

[video_player] Native Stack trace crashes when putting the app in inactive state while video is playing on Android #156451

@Tom3652

Description

@Tom3652

Steps to reproduce

  1. Run the video_player example code
  2. Click on play on the Bee video
  3. Put the app in background while the video is playing
  4. See the Stack Traces

Expected results

The behavior that was previously fixed on dispose from #156158 should also be fixed for the inactive state while the video is playing to avoid playback weirdness while resuming the app.

Actual results

You can see this Stack trace at 100% :

D/AudioTrack( 4782): getTimestamp_l(3496): device stall time corrected using current time 1108478027047474
D/BufferPoolAccessor2.0( 4782): bufferpool2 0x6f64ddde38 : 5(81920 size) total buffers - 5(81920 size) used buffers - 1/7 (recycle/alloc) - 6/25 (fetch/transfer)
D/CCodecBuffers( 4782): [c2.android.aac.decoder#432:1D-Input.Impl[N]] codec released a buffer owned by client (index 3)
D/CCodecBuffers( 4782): [c2.android.aac.decoder#432:1D-Input.Impl[N]] codec released a buffer owned by client (index 1)
E/VideoFrameReleaseHelper( 4782): Failed to call Surface.setFrameRate
E/VideoFrameReleaseHelper( 4782):   java.lang.IllegalStateException: Surface has already been released.
E/VideoFrameReleaseHelper( 4782):       at android.view.Surface.checkNotReleasedLocked(Surface.java:696)
E/VideoFrameReleaseHelper( 4782):       at android.view.Surface.setFrameRate(Surface.java:905)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseHelper$Api30.setSurfaceFrameRate(VideoFrameReleaseHelper.java:440)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseHelper.clearSurfaceFrameRate(VideoFrameReleaseHelper.java:385)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseHelper.onStopped(VideoFrameReleaseHelper.java:235)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseControl.onStopped(VideoFrameReleaseControl.java:231)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onStopped(MediaCodecVideoRenderer.java:777)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.BaseRenderer.stop(BaseRenderer.java:209)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.ensureStopped(ExoPlayerImplInternal.java:1836)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.disableRenderer(ExoPlayerImplInternal.java:1845)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:1566)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.stopInternal(ExoPlayerImplInternal.java:1523)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:577)
E/VideoFrameReleaseHelper( 4782):       at android.os.Handler.dispatchMessage(Handler.java:102)
E/VideoFrameReleaseHelper( 4782):       at android.os.Looper.loop(Looper.java:250)
E/VideoFrameReleaseHelper( 4782):       at android.os.HandlerThread.run(HandlerThread.java:67)
I/MediaCodec( 4782): (0x6fd4efc520) flush
I/ExoPlayerImpl( 4782): Release bd2c8b6 [AndroidXMedia3/1.4.1] [sofiar, moto g(8) power, motorola, 30] [media3.common, media3.exoplayer, media3.decoder, media3.datasource, media3.extractor]
I/MediaCodec( 4782): (0x6fd4f02580) flush
D/CCodecBuffers( 4782): [c2.android.aac.decoder#432:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 0
D/CCodecBuffers( 4782): [c2.android.aac.decoder#432:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 1
D/CCodecBuffers( 4782): [c2.android.aac.decoder#432:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 2
D/CCodecBuffers( 4782): [c2.android.aac.decoder#432:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 3
I/CCodecConfig( 4782): query failed after returning 19 values (BAD_INDEX)
D/CCodecConfig( 4782): c2 config diff is   c2::i32 coding.drc.compression-mode.value = 3
D/AudioTrack( 4782): ~AudioTrack(): RelativeVolumeFeature mSessionId:40289, clientId:3402
W/Codec2Client( 4782): query -- param skipped: index = 1342179345.
W/Codec2Client( 4782): query -- param skipped: index = 2415921170.
W/Codec2Client( 4782): query -- param skipped: index = 1610614798.
I/MediaCodec( 4782): (0x6fd4efc520) stop
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-0](id:12ae00000000,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
I/chatty  ( 4782): uid=10936(io.flutter.plugins.videoplayerexample) Thread-59 identical 4 lines
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-0](id:12ae00000000,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-0](id:12ae00000000,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-0](id:12ae00000000,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-0](id:12ae00000000,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
I/chatty  ( 4782): uid=10936(io.flutter.plugins.videoplayerexample) Thread-59 identical 2 lines
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-0](id:12ae00000000,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
D/SurfaceUtils( 4782): disconnecting from surface 0x7004e33840, reason disconnectFromSurface
I/MediaCodec( 4782): (0x6fd4f02580) stop
D/CCodecBufferChannel( 4782): [c2.android.aac.decoder#432] MediaCodec discarded an unknown buffer
I/chatty  ( 4782): uid=10936(io.flutter.plugins.videoplayerexample) MediaCodec_loop identical 2 lines
D/CCodecBufferChannel( 4782): [c2.android.aac.decoder#432] MediaCodec discarded an unknown buffer
I/hw-BpHwBinder( 4782): onLastStrongRef automatically unlinking death recipients
W/MessageQueue( 4782): Handler (android.os.Handler) {ef9644} sending message to a Handler on a dead thread
W/MessageQueue( 4782): java.lang.IllegalStateException: Handler (android.os.Handler) {ef9644} sending message to a Handler on a dead thread
W/MessageQueue( 4782): 	at android.os.MessageQueue.enqueueMessage(MessageQueue.java:567)
W/MessageQueue( 4782): 	at android.os.Handler.enqueueMessage(Handler.java:778)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageAtTime(Handler.java:727)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageDelayed(Handler.java:697)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessage(Handler.java:635)
W/MessageQueue( 4782): 	at android.os.Message.sendToTarget(Message.java:469)
W/MessageQueue( 4782): 	at androidx.media3.common.util.SystemHandlerWrapper$SystemMessage.sendToTarget(SystemHandlerWrapper.java:160)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImplInternal.setPlayWhenReady(ExoPlayerImplInternal.java:352)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlaybackInfoForPlayWhenReadyAndSuppressionReasonStates(ExoPlayerImpl.java:2821)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlayWhenReady(ExoPlayerImpl.java:2804)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.setPlayWhenReady(ExoPlayerImpl.java:833)
W/MessageQueue( 4782): 	at androidx.media3.common.BasePlayer.pause(BasePlayer.java:119)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayer.pause(VideoPlayer.java:134)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayerPlugin.pause(VideoPlayerPlugin.java:187)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$-CC.lambda$setUp$9(Messages.java:1067)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$$ExternalSyntheticLambda1.onMessage(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:261)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at android.os.Handler.handleCallback(Handler.java:938)
W/MessageQueue( 4782): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/MessageQueue( 4782): 	at android.os.Looper.loop(Looper.java:250)
W/MessageQueue( 4782): 	at android.app.ActivityThread.main(ActivityThread.java:7755)
W/MessageQueue( 4782): 	at java.lang.reflect.Method.invoke(Native Method)
W/MessageQueue( 4782): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
W/MessageQueue( 4782): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
W/MessageQueue( 4782): Handler (android.os.Handler) {ef9644} sending message to a Handler on a dead thread
W/MessageQueue( 4782): java.lang.IllegalStateException: Handler (android.os.Handler) {ef9644} sending message to a Handler on a dead thread
W/MessageQueue( 4782): 	at android.os.MessageQueue.enqueueMessage(MessageQueue.java:567)
W/MessageQueue( 4782): 	at android.os.Handler.enqueueMessage(Handler.java:778)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageAtTime(Handler.java:727)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageDelayed(Handler.java:697)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessage(Handler.java:635)
W/MessageQueue( 4782): 	at android.os.Message.sendToTarget(Message.java:469)
W/MessageQueue( 4782): 	at androidx.media3.common.util.SystemHandlerWrapper$SystemMessage.sendToTarget(SystemHandlerWrapper.java:160)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImplInternal.setPlayWhenReady(ExoPlayerImplInternal.java:352)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlaybackInfoForPlayWhenReadyAndSuppressionReasonStates(ExoPlayerImpl.java:2821)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlayWhenReady(ExoPlayerImpl.java:2804)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.setPlayWhenReady(ExoPlayerImpl.java:833)
W/MessageQueue( 4782): 	at androidx.media3.common.BasePlayer.play(BasePlayer.java:114)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayer.play(VideoPlayer.java:130)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayerPlugin.play(VideoPlayerPlugin.java:166)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$-CC.lambda$setUp$6(Messages.java:992)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$$ExternalSyntheticLambda8.onMessage(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:261)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at android.os.Handler.handleCallback(Handler.java:938)
W/MessageQueue( 4782): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/MessageQueue( 4782): 	at android.os.Looper.loop(Looper.java:250)
W/MessageQueue( 4782): 	at android.app.ActivityThread.main(ActivityThread.java:7755)
W/MessageQueue( 4782): 	at java.lang.reflect.Method.invoke(Native Method)
W/MessageQueue( 4782): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
W/MessageQueue( 4782): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
D/BufferPoolAccessor2.0( 4782): bufferpool2 0x6f64ddde38 : 0(0 size) total buffers - 0(0 size) used buffers - 1/7 (recycle/alloc) - 9/120 (fetch/transfer)
D/BufferPoolAccessor2.0( 4782): evictor expired: 1, evicted: 1

Code sample

Code sample
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: public_member_api_docs

/// An example of using the plugin, controlling lifecycle and playback of the
/// video.
library;

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

void main() {
  runApp(
    MaterialApp(
      home: _App(),
    ),
  );
}

class _App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        key: const ValueKey<String>('home_page'),
        appBar: AppBar(
          title: const Text('Video player example'),
          actions: <Widget>[
            IconButton(
              key: const ValueKey<String>('push_tab'),
              icon: const Icon(Icons.navigation),
              onPressed: () {
                Navigator.push<_PlayerVideoAndPopPage>(
                  context,
                  MaterialPageRoute<_PlayerVideoAndPopPage>(
                    builder: (BuildContext context) => _PlayerVideoAndPopPage(),
                  ),
                );
              },
            )
          ],
          bottom: const TabBar(
            isScrollable: true,
            tabs: <Widget>[
              Tab(
                icon: Icon(Icons.cloud),
                text: 'Remote',
              ),
              Tab(icon: Icon(Icons.insert_drive_file), text: 'Asset'),
              Tab(icon: Icon(Icons.list), text: 'List example'),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            _BumbleBeeRemoteVideo(),
            _ButterFlyAssetVideo(),
            _ButterFlyAssetVideoInList(),
          ],
        ),
      ),
    );
  }
}

class _ButterFlyAssetVideoInList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        const _ExampleCard(title: 'Item a'),
        const _ExampleCard(title: 'Item b'),
        const _ExampleCard(title: 'Item c'),
        const _ExampleCard(title: 'Item d'),
        const _ExampleCard(title: 'Item e'),
        const _ExampleCard(title: 'Item f'),
        const _ExampleCard(title: 'Item g'),
        Card(
            child: Column(children: <Widget>[
          Column(
            children: <Widget>[
              const ListTile(
                leading: Icon(Icons.cake),
                title: Text('Video video'),
              ),
              Stack(
                  alignment: FractionalOffset.bottomRight +
                      const FractionalOffset(-0.1, -0.1),
                  children: <Widget>[
                    _ButterFlyAssetVideo(),
                    Image.asset('assets/flutter-mark-square-64.png'),
                  ]),
            ],
          ),
        ])),
        const _ExampleCard(title: 'Item h'),
        const _ExampleCard(title: 'Item i'),
        const _ExampleCard(title: 'Item j'),
        const _ExampleCard(title: 'Item k'),
        const _ExampleCard(title: 'Item l'),
      ],
    );
  }
}

/// A filler card to show the video in a list of scrolling contents.
class _ExampleCard extends StatelessWidget {
  const _ExampleCard({required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          ListTile(
            leading: const Icon(Icons.airline_seat_flat_angled),
            title: Text(title),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: OverflowBar(
              alignment: MainAxisAlignment.end,
              spacing: 8.0,
              children: <Widget>[
                TextButton(
                  child: const Text('BUY TICKETS'),
                  onPressed: () {
                    /* ... */
                  },
                ),
                TextButton(
                  child: const Text('SELL TICKETS'),
                  onPressed: () {
                    /* ... */
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _ButterFlyAssetVideo extends StatefulWidget {
  @override
  _ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}

class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset('assets/Butterfly-209.mp4');

    _controller.addListener(() {
      setState(() {});
    });
    _controller.setLooping(true);
    _controller.initialize().then((_) => setState(() {}));
    _controller.play();
  }

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

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(
            padding: const EdgeInsets.only(top: 20.0),
          ),
          const Text('With assets mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller, allowScrubbing: true),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _BumbleBeeRemoteVideo extends StatefulWidget {
  @override
  _BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
}

class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
  late VideoPlayerController _controller;

  Future<ClosedCaptionFile> _loadCaptions() async {
    final String fileContents = await DefaultAssetBundle.of(context)
        .loadString('assets/bumble_bee_captions.vtt');
    return WebVTTCaptionFile(
        fileContents); // For vtt files, use WebVTTCaptionFile
  }

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.networkUrl(
      Uri.parse(
          'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'),
      closedCaptionFile: _loadCaptions(),
      videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
    );

    _controller.addListener(() {
      setState(() {});
    });
    _controller.setLooping(true);
    _controller.initialize();
  }

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

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          const Text('With remote mp4'),
          Container(
            padding: const EdgeInsets.all(20),
            child: AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: Stack(
                alignment: Alignment.bottomCenter,
                children: <Widget>[
                  VideoPlayer(_controller),
                  ClosedCaption(text: _controller.value.caption.text),
                  _ControlsOverlay(controller: _controller),
                  VideoProgressIndicator(_controller, allowScrubbing: true),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _ControlsOverlay extends StatelessWidget {
  const _ControlsOverlay({required this.controller});

  static const List<Duration> _exampleCaptionOffsets = <Duration>[
    Duration(seconds: -10),
    Duration(seconds: -3),
    Duration(seconds: -1, milliseconds: -500),
    Duration(milliseconds: -250),
    Duration.zero,
    Duration(milliseconds: 250),
    Duration(seconds: 1, milliseconds: 500),
    Duration(seconds: 3),
    Duration(seconds: 10),
  ];
  static const List<double> _examplePlaybackRates = <double>[
    0.25,
    0.5,
    1.0,
    1.5,
    2.0,
    3.0,
    5.0,
    10.0,
  ];

  final VideoPlayerController controller;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        AnimatedSwitcher(
          duration: const Duration(milliseconds: 50),
          reverseDuration: const Duration(milliseconds: 200),
          child: controller.value.isPlaying
              ? const SizedBox.shrink()
              : const ColoredBox(
                  color: Colors.black26,
                  child: Center(
                    child: Icon(
                      Icons.play_arrow,
                      color: Colors.white,
                      size: 100.0,
                      semanticLabel: 'Play',
                    ),
                  ),
                ),
        ),
        GestureDetector(
          onTap: () {
            controller.value.isPlaying ? controller.pause() : controller.play();
          },
        ),
        Align(
          alignment: Alignment.topLeft,
          child: PopupMenuButton<Duration>(
            initialValue: controller.value.captionOffset,
            tooltip: 'Caption Offset',
            onSelected: (Duration delay) {
              controller.setCaptionOffset(delay);
            },
            itemBuilder: (BuildContext context) {
              return <PopupMenuItem<Duration>>[
                for (final Duration offsetDuration in _exampleCaptionOffsets)
                  PopupMenuItem<Duration>(
                    value: offsetDuration,
                    child: Text('${offsetDuration.inMilliseconds}ms'),
                  )
              ];
            },
            child: Padding(
              padding: const EdgeInsets.symmetric(
                // Using less vertical padding as the text is also longer
                // horizontally, so it feels like it would need more spacing
                // horizontally (matching the aspect ratio of the video).
                vertical: 12,
                horizontal: 16,
              ),
              child: Text('${controller.value.captionOffset.inMilliseconds}ms'),
            ),
          ),
        ),
        Align(
          alignment: Alignment.topRight,
          child: PopupMenuButton<double>(
            initialValue: controller.value.playbackSpeed,
            tooltip: 'Playback speed',
            onSelected: (double speed) {
              controller.setPlaybackSpeed(speed);
            },
            itemBuilder: (BuildContext context) {
              return <PopupMenuItem<double>>[
                for (final double speed in _examplePlaybackRates)
                  PopupMenuItem<double>(
                    value: speed,
                    child: Text('${speed}x'),
                  )
              ];
            },
            child: Padding(
              padding: const EdgeInsets.symmetric(
                // Using less vertical padding as the text is also longer
                // horizontally, so it feels like it would need more spacing
                // horizontally (matching the aspect ratio of the video).
                vertical: 12,
                horizontal: 16,
              ),
              child: Text('${controller.value.playbackSpeed}x'),
            ),
          ),
        ),
      ],
    );
  }
}

class _PlayerVideoAndPopPage extends StatefulWidget {
  @override
  _PlayerVideoAndPopPageState createState() => _PlayerVideoAndPopPageState();
}

class _PlayerVideoAndPopPageState extends State<_PlayerVideoAndPopPage> {
  late VideoPlayerController _videoPlayerController;
  bool startedPlaying = false;

  @override
  void initState() {
    super.initState();

    _videoPlayerController =
        VideoPlayerController.asset('assets/Butterfly-209.mp4');
    _videoPlayerController.addListener(() {
      if (startedPlaying && !_videoPlayerController.value.isPlaying) {
        Navigator.pop(context);
      }
    });
  }

  @override
  void dispose() {
    _videoPlayerController.dispose();
    super.dispose();
  }

  Future<bool> started() async {
    await _videoPlayerController.initialize();
    await _videoPlayerController.play();
    startedPlaying = true;
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: FutureBuilder<bool>(
          future: started(),
          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
            if (snapshot.data ?? false) {
              return AspectRatio(
                aspectRatio: _videoPlayerController.value.aspectRatio,
                child: VideoPlayer(_videoPlayerController),
              );
            } else {
              return const Text('waiting for video to load');
            }
          },
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
I/ExoPlayerImpl( 4782): Release bd2c8b6 [AndroidXMedia3/1.4.1] [sofiar, moto g(8) power, motorola, 30] [media3.common, media3.exoplayer, media3.decoder, media3.datasource, media3.extractor]
I/ExoPlayerImpl( 4782): Init 9275e4f [AndroidXMedia3/1.4.1] [sofiar, moto g(8) power, motorola, 30]
I/MediaCodec( 4782): (0x6fd4f156b0) init name(OMX.qcom.video.decoder.avc)
I/OMXClient( 4782): IOmx service obtained
I/MediaCodec( 4782): (0x6fd4f156b0) Component Allocated (OMX.qcom.video.decoder.avc)
I/MediaCodec( 4782): (0x6fd4f156b0) configure surface(0x7004dd1950) crypto(0x0) flags(0)
D/MediaCodec( 4782): (0x6fd4f156b0) configure format: AMessage(what = 0x00000000) = {
D/MediaCodec( 4782):       int32_t max-height = 720
D/MediaCodec( 4782):       string mime = "video/avc"
D/MediaCodec( 4782):       int32_t priority = 0
D/MediaCodec( 4782):       int32_t color-standard = 1
D/MediaCodec( 4782):       Buffer csd-1 = {
D/MediaCodec( 4782):         00000000:  00 00 00 01 68 e9 7b 2c  8b                       ....h.{,.
D/MediaCodec( 4782):       }
D/MediaCodec( 4782):       int32_t color-transfer = 3
D/MediaCodec( 4782):       int32_t max-width = 1280
D/MediaCodec( 4782):       int32_t width = 1280
D/MediaCodec( 4782):       int32_t color-range = 2
D/MediaCodec( 4782):       float frame-rate = 29.975233
D/MediaCodec( 4782):       int32_t rotation-degrees = 0
D/MediaCodec( 4782):       int32_t max-input-size = 85153
D/MediaCodec( 4782):       int32_t height = 720
D/MediaCodec( 4782):       Buffer csd-0 = {
D/MediaCodec( 4782):         00000000:  00 00 00 01 67 64 00 1f  ac d9 80 50 05 bb 01 6a  ....gd.....P...j
D/MediaCodec( 4782):         00000010:  02 02 02 80 00 01 f4 80  00 75 30 07 8c 18 cd     .........u0....
D/MediaCodec( 4782):       }
D/MediaCodec( 4782):     }
D/SurfaceUtils( 4782): connecting to surface 0x7004dd1960, reason connectToSurface
I/MediaCodec( 4782): [OMX.qcom.video.decoder.avc] setting surface generation to 4896770
D/SurfaceUtils( 4782): disconnecting from surface 0x7004dd1960, reason connectToSurface(reconnect)
D/SurfaceUtils( 4782): connecting to surface 0x7004dd1960, reason connectToSurface(reconnect)
I/ACodec  ( 4782): DRC Mode: Dynamic Buffer Mode
I/ExtendedACodec( 4782): setupVideoDecoder()
I/ACodec  ( 4782): [OMX.qcom.video.decoder.avc] setupVideoDecoder Width Height (1280x720)
I/ACodec  ( 4782): mime (video/avc) compressionFormat (7)
I/ExtendedACodec( 4782): Decoder will be in frame by frame mode
I/MediaCodec( 4782): (0x6fd4f156b0) start
D/SurfaceUtils( 4782): set up nativeWindow 0x7004dd1960 for 1280x720, color 0x7fa30c06, rotation 0, usage 0x20002900
I/MediaCodec( 4782): (0x6fd4f156b0) kWhatStartCompleted
I/MediaCodec( 4782): (0x6fd4f0b610) init name(c2.android.aac.decoder)
D/CCodec  ( 4782): allocate(c2.android.aac.decoder)
I/CCodec  ( 4782): Created component [c2.android.aac.decoder]
D/CCodecConfig( 4782): read media type: audio/mp4a-latm
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: algo.buffers.max-count.values
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: output.subscribed-indices.values
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: input.buffers.allocator-ids.values
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: output.buffers.allocator-ids.values
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: algo.buffers.allocator-ids.values
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: output.buffers.pool-ids.values
D/ReflectedParamUpdater( 4782): extent() != 1 for single value type: algo.buffers.pool-ids.values
I/CCodecConfig( 4782): query failed after returning 19 values (BAD_INDEX)
D/CCodecConfig( 4782): c2 config diff is Dict {
D/CCodecConfig( 4782):   c2::u32 coded.aac-packaging.value = 0
D/CCodecConfig( 4782):   c2::u32 coded.bitrate.value = 64000
D/CCodecConfig( 4782):   c2::u32 coded.pl.level = 0
D/CCodecConfig( 4782):   c2::u32 coded.pl.profile = 8192
D/CCodecConfig( 4782):   c2::i32 coding.drc.album-mode.value = 0
D/CCodecConfig( 4782):   c2::float coding.drc.attenuation-factor.value = 1
D/CCodecConfig( 4782):   c2::float coding.drc.boost-factor.value = 1
D/CCodecConfig( 4782):   c2::i32 coding.drc.compression-mode.value = 3
D/CCodecConfig( 4782):   c2::i32 coding.drc.effect-type.value = 3
D/CCodecConfig( 4782):   c2::float coding.drc.encoded-level.value = 0.25
D/CCodecConfig( 4782):   c2::float coding.drc.reference-level.value = -16
D/CCodecConfig( 4782):   c2::u32 input.buffers.max-size.value = 8192
D/CCodecConfig( 4782):   c2::u32 input.delay.value = 0
D/CCodecConfig( 4782):   string input.media-type.value = "audio/mp4a-latm"
D/CCodecConfig( 4782):   c2::u32 output.delay.value = 2
D/CCodecConfig( 4782):   c2::float output.drc.output-loudness.value = 0.25
D/CCodecConfig( 4782):   string output.media-type.value = "audio/raw"
D/CCodecConfig( 4782):   c2::u32 raw.channel-count.value = 1
D/CCodecConfig( 4782):   c2::u32 raw.max-channel-count.value = 8
D/CCodecConfig( 4782):   c2::u32 raw.sample-rate.value = 44100
D/CCodecConfig( 4782): }
I/MediaCodec( 4782): (0x6fd4f0b610) Component Allocated (c2.android.aac.decoder)
I/MediaCodec( 4782): (0x6fd4f0b610) configure surface(0x0) crypto(0x0) flags(0)
D/MediaCodec( 4782): (0x6fd4f0b610) configure format: AMessage(what = 0x00000000) = {
D/MediaCodec( 4782):       float operating-rate = 48000.000000
D/MediaCodec( 4782):       int32_t sample-rate = 48000
D/MediaCodec( 4782):       string mime = "audio/mp4a-latm"
D/MediaCodec( 4782):       int32_t channel-count = 2
D/MediaCodec( 4782):       int32_t priority = 0
D/MediaCodec( 4782):       int32_t max-input-size = 628
D/MediaCodec( 4782):       Buffer csd-0 = {
D/MediaCodec( 4782):         00000000:  11 90                                             ..
D/MediaCodec( 4782):       }
D/MediaCodec( 4782):     }
D/CCodec  ( 4782): [c2.android.aac.decoder] buffers are bound to CCodec for this session
D/CCodecConfig( 4782): no c2 equivalents for flags
D/CCodecConfig( 4782): config failed => CORRUPTED
D/CCodecConfig( 4782): c2 config diff is   c2::u32 raw.channel-count.value = 2
D/CCodecConfig( 4782):   c2::u32 raw.sample-rate.value = 48000
W/Codec2Client( 4782): query -- param skipped: index = 1107298332.
D/CCodec  ( 4782): client requested max input size 628, which is smaller than what component recommended (16384); overriding with component recommendation.
W/CCodec  ( 4782): This behavior is subject to change. It is recommended that app developers double check whether the requested max input size is in reasonable range.
D/CCodec  ( 4782): setup formats input: AMessage(what = 0x00000000) = {
D/CCodec  ( 4782):   int32_t aac-drc-album-mode = 0
D/CCodec  ( 4782):   int32_t aac-drc-boost-level = 127
D/CCodec  ( 4782):   int32_t aac-drc-cut-level = 127
D/CCodec  ( 4782):   int32_t aac-drc-effect-type = 3
D/CCodec  ( 4782):   int32_t aac-drc-heavy-compression = 3
D/CCodec  ( 4782):   int32_t aac-encoded-target-level = -1
D/CCodec  ( 4782):   int32_t aac-max-output-channel_count = 8
D/CCodec  ( 4782):   int32_t aac-target-ref-level = 64
D/CCodec  ( 4782):   int32_t channel-count = 2
D/CCodec  ( 4782):   int32_t level = 0
D/CCodec  ( 4782):   int32_t max-input-size = 16384
D/CCodec  ( 4782):   string mime = "audio/mp4a-latm"
D/CCodec  ( 4782):   int32_t profile = 2
D/CCodec  ( 4782):   int32_t sample-rate = 48000
D/CCodec  ( 4782): } and output: AMessage(what = 0x00000000) = {
D/CCodec  ( 4782):   int32_t aac-drc-album-mode = 0
D/CCodec  ( 4782):   int32_t aac-drc-boost-level = 127
D/CCodec  ( 4782):   int32_t aac-drc-cut-level = 127
D/CCodec  ( 4782):   int32_t aac-drc-effect-type = 3
D/CCodec  ( 4782):   int32_t aac-drc-heavy-compression = 3
D/CCodec  ( 4782):   int32_t aac-drc-output-loudness = -1
D/CCodec  ( 4782):   int32_t aac-encoded-target-level = -1
D/CCodec  ( 4782):   int32_t aac-max-output-channel_count = 8
D/CCodec  ( 4782):   int32_t aac-target-ref-level = 64
D/CCodec  ( 4782):   int32_t channel-count = 2
D/CCodec  ( 4782):   string mime = "audio/raw"
D/CCodec  ( 4782):   int32_t sample-rate = 48000
D/CCodec  ( 4782): }
I/MediaCodec( 4782): (0x6fd4f0b610) start
W/Codec2Client( 4782): query -- param skipped: index = 1342179345.
W/Codec2Client( 4782): query -- param skipped: index = 2415921170.
W/Codec2Client( 4782): query -- param skipped: index = 1610614798.
E/FMQ     ( 4782): grantorIdx must be less than 3
E/FMQ     ( 4782): grantorIdx must be less than 3
D/CCodecBufferChannel( 4782): [c2.android.aac.decoder#532] Created input block pool with allocatorID 16 => poolID 18 - OK (0)
D/BufferPoolAccessor2.0( 4782): bufferpool2 0x6f64ddde38 : 0(0 size) total buffers - 0(0 size) used buffers - 1/7 (recycle/alloc) - 9/120 (fetch/transfer)
D/BufferPoolAccessor2.0( 4782): Destruction - bufferpool2 0x6f64ddde38 cached: 0/0M, 0/0% in use; allocs: 7, 14% recycled; transfers: 120, 93% unfetched
I/CCodecBufferChannel( 4782): [c2.android.aac.decoder#532] Created output block pool with allocatorID 16 => poolID 3527 - OK
D/CCodecBufferChannel( 4782): [c2.android.aac.decoder#532] Configured output block pool ids 3527 => OK
I/MediaCodec( 4782): (0x6fd4f0b610) kWhatStartCompleted
E/FMQ     ( 4782): grantorIdx must be less than 3
E/FMQ     ( 4782): grantorIdx must be less than 3
D/CCodecConfig( 4782): c2 config diff is   c2::i32 coding.drc.compression-mode.value = 1
D/CCodecConfig( 4782):   c2::u32 raw.channel-mask.value = 12
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:Output[N]] popFromStashAndRegister: output format changed to AMessage(what = 0x00000000) = {
D/CCodecBuffers( 4782):   int32_t aac-drc-album-mode = 0
D/CCodecBuffers( 4782):   int32_t aac-drc-boost-level = 127
D/CCodecBuffers( 4782):   int32_t aac-drc-cut-level = 127
D/CCodecBuffers( 4782):   int32_t aac-drc-effect-type = 3
D/CCodecBuffers( 4782):   int32_t aac-drc-heavy-compression = 1
D/CCodecBuffers( 4782):   int32_t aac-drc-output-loudness = -1
D/CCodecBuffers( 4782):   int32_t aac-encoded-target-level = -1
D/CCodecBuffers( 4782):   int32_t aac-max-output-channel_count = 8
D/CCodecBuffers( 4782):   int32_t aac-target-ref-level = 64
D/CCodecBuffers( 4782):   int32_t channel-count = 2
D/CCodecBuffers( 4782):   string mime = "audio/raw"
D/CCodecBuffers( 4782):   int32_t sample-rate = 48000
D/CCodecBuffers( 4782): }
D/AudioTrack( 4782): createTrack_l(): RelativeVolumeFeature, mStreamType -1, streamType 3, attributes: usage=1 content=3 flags=0xa00 tags=[], percentage=1.000000 clientId=3403
D/AudioTrack( 4782): createTrack_l: RelativeVolumeFeature, mRelativePercentage:1.000000
D/AudioTrack( 4782): setVolume: RelativeVolumeFeature, mRelativePercentage:1.000000, left:1.000000, right:1.000000
I/MediaCodec( 4782): (0x6fd4f156b0) setParameters
D/ImageReaderSurfaceProducer( 4782): ImageTextureEntry can't wait on the fence on Android < 33
D/AudioTrack( 4782): getTimestamp_l(3497): device stall time corrected using current time 1108765589477267
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:1D-Input.Impl[N]] codec released a buffer owned by client (index 4)
I/ExoPlayerImpl( 4782): Release 9275e4f [AndroidXMedia3/1.4.1] [sofiar, moto g(8) power, motorola, 30] [media3.common, media3.exoplayer, media3.decoder, media3.datasource, media3.extractor]
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:1D-Input.Impl[N]] codec released a buffer owned by client (index 0)
E/VideoFrameReleaseHelper( 4782): Failed to call Surface.setFrameRate
E/VideoFrameReleaseHelper( 4782):   java.lang.IllegalStateException: Surface has already been released.
E/VideoFrameReleaseHelper( 4782):       at android.view.Surface.checkNotReleasedLocked(Surface.java:696)
E/VideoFrameReleaseHelper( 4782):       at android.view.Surface.setFrameRate(Surface.java:905)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseHelper$Api30.setSurfaceFrameRate(VideoFrameReleaseHelper.java:440)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseHelper.clearSurfaceFrameRate(VideoFrameReleaseHelper.java:385)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseHelper.onStopped(VideoFrameReleaseHelper.java:235)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.VideoFrameReleaseControl.onStopped(VideoFrameReleaseControl.java:231)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onStopped(MediaCodecVideoRenderer.java:777)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.BaseRenderer.stop(BaseRenderer.java:209)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.ensureStopped(ExoPlayerImplInternal.java:1836)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.disableRenderer(ExoPlayerImplInternal.java:1845)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:1566)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.stopInternal(ExoPlayerImplInternal.java:1523)
E/VideoFrameReleaseHelper( 4782):       at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:577)
E/VideoFrameReleaseHelper( 4782):       at android.os.Handler.dispatchMessage(Handler.java:102)
E/VideoFrameReleaseHelper( 4782):       at android.os.Looper.loop(Looper.java:250)
E/VideoFrameReleaseHelper( 4782):       at android.os.HandlerThread.run(HandlerThread.java:67)
I/MediaCodec( 4782): (0x6fd4f156b0) flush
I/MediaCodec( 4782): (0x6fd4f0b610) flush
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 0
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 1
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 2
D/CCodecBuffers( 4782): [c2.android.aac.decoder#532:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 3
I/CCodecConfig( 4782): query failed after returning 19 values (BAD_INDEX)
D/CCodecConfig( 4782): c2 config diff is   c2::i32 coding.drc.compression-mode.value = 3
W/Codec2Client( 4782): query -- param skipped: index = 1342179345.
W/Codec2Client( 4782): query -- param skipped: index = 2415921170.
W/Codec2Client( 4782): query -- param skipped: index = 1610614798.
I/MediaCodec( 4782): (0x6fd4f156b0) stop
D/AudioTrack( 4782): ~AudioTrack(): RelativeVolumeFeature mSessionId:40297, clientId:3403
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
I/chatty  ( 4782): uid=10936(io.flutter.plugins.videoplayerexample) Thread-125 identical 5 lines
E/BufferQueueProducer( 4782): [ImageReader-1x1f22m5-4782-1](id:12ae00000001,api:3,p:4782,c:4782) cancelBuffer: BufferQueue has been abandoned
D/SurfaceUtils( 4782): disconnecting from surface 0x7004dd1960, reason disconnectFromSurface
I/MediaCodec( 4782): (0x6fd4f0b610) stop
D/CCodecBufferChannel( 4782): [c2.android.aac.decoder#532] MediaCodec discarded an unknown buffer
I/chatty  ( 4782): uid=10936(io.flutter.plugins.videoplayerexample) MediaCodec_loop identical 2 lines
D/CCodecBufferChannel( 4782): [c2.android.aac.decoder#532] MediaCodec discarded an unknown buffer
I/hw-BpHwBinder( 4782): onLastStrongRef automatically unlinking death recipients
D/BufferPoolAccessor2.0( 4782): evictor expired: 1, evicted: 0
W/MessageQueue( 4782): Handler (android.os.Handler) {57fe0d4} sending message to a Handler on a dead thread
W/MessageQueue( 4782): java.lang.IllegalStateException: Handler (android.os.Handler) {57fe0d4} sending message to a Handler on a dead thread
W/MessageQueue( 4782): 	at android.os.MessageQueue.enqueueMessage(MessageQueue.java:567)
W/MessageQueue( 4782): 	at android.os.Handler.enqueueMessage(Handler.java:778)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageAtTime(Handler.java:727)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageDelayed(Handler.java:697)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessage(Handler.java:635)
W/MessageQueue( 4782): 	at android.os.Message.sendToTarget(Message.java:469)
W/MessageQueue( 4782): 	at androidx.media3.common.util.SystemHandlerWrapper$SystemMessage.sendToTarget(SystemHandlerWrapper.java:160)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImplInternal.setPlayWhenReady(ExoPlayerImplInternal.java:352)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlaybackInfoForPlayWhenReadyAndSuppressionReasonStates(ExoPlayerImpl.java:2821)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlayWhenReady(ExoPlayerImpl.java:2804)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.setPlayWhenReady(ExoPlayerImpl.java:833)
W/MessageQueue( 4782): 	at androidx.media3.common.BasePlayer.pause(BasePlayer.java:119)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayer.pause(VideoPlayer.java:134)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayerPlugin.pause(VideoPlayerPlugin.java:187)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$-CC.lambda$setUp$9(Messages.java:1067)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$$ExternalSyntheticLambda1.onMessage(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:261)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at android.os.Handler.handleCallback(Handler.java:938)
W/MessageQueue( 4782): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/MessageQueue( 4782): 	at android.os.Looper.loop(Looper.java:250)
W/MessageQueue( 4782): 	at android.app.ActivityThread.main(ActivityThread.java:7755)
W/MessageQueue( 4782): 	at java.lang.reflect.Method.invoke(Native Method)
W/MessageQueue( 4782): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
W/MessageQueue( 4782): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
W/MessageQueue( 4782): Handler (android.os.Handler) {57fe0d4} sending message to a Handler on a dead thread
W/MessageQueue( 4782): java.lang.IllegalStateException: Handler (android.os.Handler) {57fe0d4} sending message to a Handler on a dead thread
W/MessageQueue( 4782): 	at android.os.MessageQueue.enqueueMessage(MessageQueue.java:567)
W/MessageQueue( 4782): 	at android.os.Handler.enqueueMessage(Handler.java:778)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageAtTime(Handler.java:727)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessageDelayed(Handler.java:697)
W/MessageQueue( 4782): 	at android.os.Handler.sendMessage(Handler.java:635)
W/MessageQueue( 4782): 	at android.os.Message.sendToTarget(Message.java:469)
W/MessageQueue( 4782): 	at androidx.media3.common.util.SystemHandlerWrapper$SystemMessage.sendToTarget(SystemHandlerWrapper.java:160)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImplInternal.setPlayWhenReady(ExoPlayerImplInternal.java:352)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlaybackInfoForPlayWhenReadyAndSuppressionReasonStates(ExoPlayerImpl.java:2821)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.updatePlayWhenReady(ExoPlayerImpl.java:2804)
W/MessageQueue( 4782): 	at androidx.media3.exoplayer.ExoPlayerImpl.setPlayWhenReady(ExoPlayerImpl.java:833)
W/MessageQueue( 4782): 	at androidx.media3.common.BasePlayer.play(BasePlayer.java:114)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayer.play(VideoPlayer.java:130)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.VideoPlayerPlugin.play(VideoPlayerPlugin.java:166)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$-CC.lambda$setUp$6(Messages.java:992)
W/MessageQueue( 4782): 	at io.flutter.plugins.videoplayer.Messages$AndroidVideoPlayerApi$$ExternalSyntheticLambda8.onMessage(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:261)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
W/MessageQueue( 4782): 	at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
W/MessageQueue( 4782): 	at android.os.Handler.handleCallback(Handler.java:938)
W/MessageQueue( 4782): 	at android.os.Handler.dispatchMessage(Handler.java:99)
W/MessageQueue( 4782): 	at android.os.Looper.loop(Looper.java:250)
W/MessageQueue( 4782): 	at android.app.ActivityThread.main(ActivityThread.java:7755)
W/MessageQueue( 4782): 	at java.lang.reflect.Method.invoke(Native Method)
W/MessageQueue( 4782): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
W/MessageQueue( 4782): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.24.3, on macOS 15.0.1 24A348 darwin-x64, locale fr-FR)
    • Flutter version 3.24.3 on channel stable at /Users/tommydeshairs/Desktop/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2663184aa7 (4 weeks ago), 2024-09-11 16:27:48 -0500
    • Engine revision 36335019a8
    • Dart version 3.5.3
    • DevTools version 2.37.3

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
    • Android SDK at /Users/tommydeshairs/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915915-b509.11)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.0)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16A242d
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915915-b509.11)

[✓] VS Code (version 1.94.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (4 available)
    • moto g 8 power (mobile) • adb-ZY22BNDW2C-yyjDO7._adb-tls-connect._tcp • android-arm64  • Android 11 (API 30)
    • Now You See Me (mobile) • 00008020-001204401E78002E                   • ios            • iOS 18.0.1 22A3370
    • macOS (desktop)         • macos                                       • darwin-x64     • macOS 15.0.1 24A348 darwin-x64
    • Chrome (web)            • chrome                                      • web-javascript • Google Chrome 129.0.6668.91

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listfound in release: 3.24Found to occur in 3.24found in release: 3.26Found to occur in 3.26has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: video_playerThe Video Player pluginpackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-androidOwned by Android platform team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions