Closed qinjing100 closed 1 month ago
Thanks for the report @qinjing100 share_plus and mime are third party packages. Does the same behavior persists without using these package's code implementation and using the intent chooser that Android provides to share the video ? If so, please provide us updated code sample.
@darshankawar Thanks for your reply. Because Flutter Official share plugin has been replaced by the share_plus, I do not know how to use intent chooser that Android provides manually.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:share_plus/share_plus.dart';
import 'package:mime/mime.dart';
import 'package:path/path.dart';
class ButterFlyAssetVideo extends StatefulWidget {
@override
ButterFlyAssetVideoState createState() => ButterFlyAssetVideoState();
}
class ButterFlyAssetVideoState extends State<ButterFlyAssetVideo>
with WidgetsBindingObserver {
late VideoPlayerController _controller;
String fp = '/storage/emulated/0/Download/833095631108348966.mp4';
@override
void initState() {
super.initState();
// _controller = VideoPlayerController.file(File(fp),);
// _controller.addListener(() {
// setState(() {});
// });
// _controller.setLooping(true);
// _controller.initialize().then((_) => setState(() {}));
// _controller.play();
WidgetsBinding.instance.addObserver(this);
initialize();
}
initialize() {
_controller = VideoPlayerController.file(File(fp),
videoPlayerOptions: VideoPlayerOptions(
allowBackgroundPlayback: true,
));
_controller.addListener(() {
setState(() {});
});
_controller.setLooping(true);
_controller.initialize().then((_) => setState(() {}));
_controller.play();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
debugPrint("didChangeAppLifecycleState $state");
switch (state) {
case AppLifecycleState.inactive:
{
_controller.dispose();
}
break;
case AppLifecycleState.paused:
{
_controller.dispose();
}
break;
case AppLifecycleState.detached:
{
_controller.dispose();
}
break;
case AppLifecycleState.resumed:
{
initialize();
}
break;
default:
{
//statements;
}
break;
}
}
@override
void dispose() {
_controller.dispose();
WidgetsBinding.instance.removeObserver(this);
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 _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'),
),
),
),
Positioned(
// alignment: Alignment.bottomRight,
bottom: 32,
right: 8,
child: IconButton(
onPressed: () async {
var medias = List<String>.filled(
1, '/storage/emulated/0/Download/833095631108348966.mp4');
// share file
try {
await shareWithResult(medias);
} catch (e) {
debugPrint('share error: $e');
}
},
icon:
const Icon(Icons.share_outlined, color: Colors.white, size: 36),
),
),
],
);
}
Future<void> shareWithResult(List<String> medias) async {
ShareResult shareResult;
final files = <XFile>[];
for (var i = 0; i < medias.length; i++) {
var mt = lookupMimeType(medias[i]);
debugPrint('file: ${medias[i]}, type: $mt');
XFile xfile;
if (mt != null && mt.startsWith('image')) {
debugPrint('add image file to share!');
xfile = XFile(medias[i], name: basename(medias[i]), mimeType: mt);
} else {
xfile = XFile(medias[i], name: basename(medias[i]));
}
// only support share one file per time
if (files.isEmpty) {
files.add(xfile);
}
}
String status = 'share result: ';
try {
shareResult = await Share.shareXFiles(
files,
text: 'share text',
subject: 'share subject',
);
if (shareResult.status == ShareResultStatus.success) {
status = "$status: share succeed.";
} else if (shareResult.status == ShareResultStatus.dismissed) {
status = "$status: share dismissed.";
} else {
status = "$status: share unavailable!";
}
} catch (e) {
debugPrint('share error: $e');
}
}
}
If i reinitialize the controller manually when AppLifecycleState resumed back, the problem disappear. But another problem occur, the video plays from zero (because of the reinitialize operation).
So I think of there is something bug in the _VideoAppLifeCycleObserver of the video controller.
Thanks a lot for your time.
Thanks for the update. The code sample assumes and uses local path to download the video and play, but at my end it won't work. Is there a way to use file from asset or from network directly which still shows the issue ?
@darshankawar Thanks for your reply. I update the sample code .
// 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.
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
import 'package:share_plus/share_plus.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.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(this.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;
static const String videoName = 'Butterfly-209.mp4';
Future<String> copyVideo(String filename) async {
final tempDir = await getTemporaryDirectory();
ByteData bytes = await rootBundle.load("assets/$filename");
final assetPath = '${tempDir.path}/$filename';
File file = await File(assetPath).create();
await file.writeAsBytes(bytes.buffer.asUint8List());
debugPrint('file path: ${file.path}');
return file.path;
}
@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'),
),
),
),
Positioned(
// alignment: Alignment.bottomRight,
bottom: 30,
right: 8,
child: IconButton(
onPressed: () async {
final tempFilePath = await copyVideo(videoName);
debugPrint('temp file path: $tempFilePath');
var medias = List<String>.filled(1, tempFilePath);
// share
try {
await shareWithResult(medias);
} catch (e) {
debugPrint('share error: $e');
}
},
icon: const Icon(Icons.share_outlined, color: Colors.red, size: 30),
),
),
],
);
}
Future<void> shareWithResult(List<String> medias) async {
ShareResult shareResult;
final files = <XFile>[];
for (var i = 0; i < medias.length; i++) {
XFile xfile;
xfile = XFile(medias[i], name: basename(medias[i]));
// only support share one file per time
if (files.isEmpty) {
files.add(xfile);
}
}
String status = 'share result: ';
try {
shareResult = await Share.shareXFiles(
files,
text: 'share text',
subject: 'share subject',
);
if (shareResult.status == ShareResultStatus.success) {
status = "$status: ${shareResult.raw}";
} else if (shareResult.status == ShareResultStatus.dismissed) {
status = "$status: shareDismissed.";
} else {
status = "$status: shareUnavailable!";
}
} catch (e) {
debugPrint('share error: $e');
}
}
}
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(this.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');
}
},
),
),
);
}
}
Asset Tab, I add a Share button, you can have a try. First click the red share button, then dissmiss share. then the video state become abnormal, play or pause not work, the video progress indicator keep moving.
Thanks for your time.
Thanks for the update. I see below after clicking on share button and then dismissing:
https://github.com/user-attachments/assets/cc294d55-ce80-48f9-b6f7-4d83986b0bcb
Stable : 3.24.2
Master: 3.25.0-1.0.pre.269
@darshankawar Thanks for your reply. I found on flutter 3.22.3 it works well. maybe there is something bug of _VideoAppLifeCycle (video_player 2.9.1) with flutter sdk (3.24.0 +) appLifeCycle. hope some one can fix it as soon as possible.
Same issue for me but when put the screen off or when put the app in background. The app stop playing video. Works well with flutter 3.22.3.
Another workaround
# pubspec.yaml
dependencies:
video_player: ^2.9.1
dependency_overrides:
video_player_android: 2.7.1
Maybe video_player_andriod's Impeller Support is the problem?
video_player_android changelog
## 2.7.3. <-- broken with latest video_palyer & flutter
* Updates Media3-ExoPlayer to 1.4.1.
## 2.7.2. <-- broken with latest video_palyer & flutter
* Updates minimum supported SDK version to Flutter 3.24/Dart 3.5.
* Re-adds Impeller support.
## 2.7.1. <----------- work well with latest video_palyer & flutter
* Revert Impeller support.
## 2.7.0. <-- not tested
* Re-adds [support for Impeller](https://docs.flutter.dev/release/breaking-changes/android-surface-plugins).
## 2.6.0. <----------- work well with latest video_palyer & flutter
* Adds RTSP support.
@matanlurey Do you think this is related to the work you had to do to support Impeller?
I have a 1-line fix for the share/share_plus regression that should be easy to test and land:
final class VideoPlayer implements TextureRegistry.SurfaceProducer.Callback {
@@ -86,8 +88,8 @@ final class VideoPlayer implements TextureRegistry.SurfaceProducer.Callback {
@RestrictTo(RestrictTo.Scope.LIBRARY)
public void onSurfaceCreated() {
- exoPlayer = createVideoPlayer();
if (savedStateDuring != null) {
+ exoPlayer = createVideoPlayer();
savedStateDuring.restore(exoPlayer);
savedStateDuring = null;
}
Longer-term I want to rename onSurfaceCreated
to onSurfaceAvailable
and add better docs
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v
and a minimal reproduction of the issue.
Steps to reproduce
Expected results
Actual results
Code sample
Code sample
```dart import 'dart:io'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; import 'package:share_plus/share_plus.dart'; import 'package:mime/mime.dart'; import 'package:path/path.dart'; class ButterFlyAssetVideo extends StatefulWidget { @override ButterFlyAssetVideoState createState() => ButterFlyAssetVideoState(); } class ButterFlyAssetVideoState extends StateScreenshots or Video
Screenshots / Video demonstration
### 1. play video from file ### 2. click share > ### 3. dissmiss share, resume play video page > ### 4. state error, play or pause button can not work, and video progress indicator keep moving >Logs
Logs
```console [+1460 ms] I/flutter (19615): file: /storage/emulated/0/Download/1134977543617888510.mp4, type: video/mp4 [ +563 ms] V/CCodec (19615): watch for 1 codecs [ ] D/PipelineWatcher(19615): DEBUG: elapsed 2 / 2 [+1727 ms] D/BufferPoolAccessor2.0(19615): bufferpool2 0xb40000773a80d028 : 6(49152 size) total buffers - 5(40960 size) used buffers - 1/7 (recycle/alloc) - 6/44 (fetch/transfer) [ ] D/BufferPoolAccessor2.0(19615): evictor expired: 1, evicted: 1 [ +55 ms] I/FA (19615): Application backgrounded at: timestamp_millis: 1725375039034 [+12961 ms] I/ExoPlayerImpl(19615): Init 6fa0e3a [AndroidXMedia3/1.4.0] [PD2164, V2164A, vivo, 30] [ +42 ms] W/AString (19615): ctor got NULL, using empty string instead [ ] D/MediaCodec(19615): CreateByComponentName,componentName is:OMX.MTK.VIDEO.DECODER.AVC [ ] I/ACodec (19615): mIsVivoLogEnable = 0 [ +4 ms] I/OMXClient(19615): IOmx service obtained [ +3 ms] D/MediaCodec(19615): flushMediametrics [ ] D/SurfaceUtils(19615): connecting to surface 0xb4000073e82d8010, reason connectToSurface [ ] E/BufferQueueProducer(19615): [ImageReader-1x1f22m5-19615-0](id:4c9f00000000,api:3,p:19615,c:19615) connect: already connected (cur=3 req=3) [ ] E/SurfaceUtils(19615): Failed to connect to surface 0xb4000073e82d8010, err -22 [ ] E/MediaCodec(19615): nativeWindowConnect returned an error: Invalid argument (-22) [ ] E/MediaCodec(19615): configure failed with err 0xffffffea, resetting... [ +3 ms] I/ACodec (19615): mIsVivoLogEnable = 0 [ ] I/OMXClient(19615): IOmx service obtained [ +6 ms] W/MediaCodecRenderer(19615): Failed to initialize decoder: OMX.MTK.VIDEO.DECODER.AVC [ ] W/MediaCodecRenderer(19615): java.lang.IllegalArgumentException [ ] W/MediaCodecRenderer(19615): at android.media.MediaCodec.native_configure(Native Method) [ ] W/MediaCodecRenderer(19615): at android.media.MediaCodec.configure(MediaCodec.java:2158) [ ] W/MediaCodecRenderer(19615): at android.media.MediaCodec.configure(MediaCodec.java:2074) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter$Factory.createAdapter(SynchronousMediaCodecAdapter.java:53) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.DefaultMediaCodecAdapterFactory.createAdapter(DefaultMediaCodecAdapterFactory.java:139) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:1225) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1137) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:588) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1602) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1182) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:1042) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:860) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1018) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1136) [ ] W/MediaCodecRenderer(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:561) [ ] W/MediaCodecRenderer(19615): at android.os.Handler.dispatchMessage(Handler.java:102) [ ] W/MediaCodecRenderer(19615): at android.os.Looper.loop(Looper.java:257) [ ] W/MediaCodecRenderer(19615): at android.os.HandlerThread.run(HandlerThread.java:67) [ ] E/MediaCodecVideoRenderer(19615): Video codec error [ ] E/MediaCodecVideoRenderer(19615): androidx.media3.exoplayer.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.MTK.VIDEO.DECODER.AVC, Format(1, null, null, video/avc, avc1.64001F, -1, null, [720, 1280, 30.0, ColorInfo(BT709, Limited range, SDR SMPTE 170M, false, 8bit Luma, 8bit Chroma)], [-1, -1]) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1144) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:588) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1602) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1182) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:1042) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:860) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1018) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1136) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:561) [ ] E/MediaCodecVideoRenderer(19615): at android.os.Handler.dispatchMessage(Handler.java:102) [ ] E/MediaCodecVideoRenderer(19615): at android.os.Looper.loop(Looper.java:257) [ ] E/MediaCodecVideoRenderer(19615): at android.os.HandlerThread.run(HandlerThread.java:67) [ ] E/MediaCodecVideoRenderer(19615): Caused by: java.lang.IllegalArgumentException [ ] E/MediaCodecVideoRenderer(19615): at android.media.MediaCodec.native_configure(Native Method) [ ] E/MediaCodecVideoRenderer(19615): at android.media.MediaCodec.configure(MediaCodec.java:2158) [ ] E/MediaCodecVideoRenderer(19615): at android.media.MediaCodec.configure(MediaCodec.java:2074) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter$Factory.createAdapter(SynchronousMediaCodecAdapter.java:53) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.DefaultMediaCodecAdapterFactory.createAdapter(DefaultMediaCodecAdapterFactory.java:139) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:1225) [ ] E/MediaCodecVideoRenderer(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1137) [ ] E/MediaCodecVideoRenderer(19615): ... 11 more [ ] E/ExoPlayerImplInternal(19615): Playback error [ ] E/ExoPlayerImplInternal(19615): androidx.media3.exoplayer.ExoPlaybackException: MediaCodecVideoRenderer error, index=0, format=Format(1, null, null, video/avc, avc1.64001F, -1, null, [720, 1280, 30.0, ColorInfo(BT709, Limited range, SDR SMPTE 170M, false, 8bit Luma, 8bit Chroma)], [-1, -1]), format_supported=YES [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:640) [ ] E/ExoPlayerImplInternal(19615): at android.os.Handler.dispatchMessage(Handler.java:102) [ ] E/ExoPlayerImplInternal(19615): at android.os.Looper.loop(Looper.java:257) [ ] E/ExoPlayerImplInternal(19615): at android.os.HandlerThread.run(HandlerThread.java:67) [ ] E/ExoPlayerImplInternal(19615): Caused by: androidx.media3.exoplayer.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.MTK.VIDEO.DECODER.AVC, Format(1, null, null, video/avc, avc1.64001F, -1, null, [720, 1280, 30.0, ColorInfo(BT709, Limited range, SDR SMPTE 170M, false, 8bit Luma, 8bit Chroma)], [-1, -1]) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1144) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecOrBypass(MediaCodecRenderer.java:588) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1602) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:1182) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:1042) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:860) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1018) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1136) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:561) [ ] E/ExoPlayerImplInternal(19615): ... 3 more [ ] E/ExoPlayerImplInternal(19615): Caused by: java.lang.IllegalArgumentException [ ] E/ExoPlayerImplInternal(19615): at android.media.MediaCodec.native_configure(Native Method) [ ] E/ExoPlayerImplInternal(19615): at android.media.MediaCodec.configure(MediaCodec.java:2158) [ ] E/ExoPlayerImplInternal(19615): at android.media.MediaCodec.configure(MediaCodec.java:2074) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter$Factory.createAdapter(SynchronousMediaCodecAdapter.java:53) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.DefaultMediaCodecAdapterFactory.createAdapter(DefaultMediaCodecAdapterFactory.java:139) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:1225) [ ] E/ExoPlayerImplInternal(19615): at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:1137) [ ] E/ExoPlayerImplInternal(19615): ... 11 more [ ] D/MediaCodec(19615): flushMediametrics [ +7 ms] D/MediaCodec(19615): flushMediametrics [+1669 ms] I/TRuntime.CctTransportBackend(19615): Making request to: https://firebaselogging-pa.googleapis.com/v1/firelog/legacy/batchlog ```Flutter Doctor output
Doctor output
```console [✓] Flutter (Channel stable, 3.24.0, on macOS 14.6.1 23G93 darwin-x64, locale zh-Hans-HK) • Flutter version 3.24.0 on channel stable at /Users/bruce/fvm/versions/3.24.0 • Upstream repository https://github.com/flutter/flutter.git • Framework revision 80c2e84975 (5 weeks ago), 2024-07-30 23:06:49 +0700 • Engine revision b8800d88be • Dart version 3.5.0 • DevTools version 2.37.2 • Pub download mirror https://pub.flutter-io.cn • Flutter download mirror https://storage.flutter-io.cn [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/bruce/Library/Android/sdk • Platform android-34, build-tools 34.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160) • All Android licenses accepted. [!] Xcode - develop for iOS and macOS (Xcode 15.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15E204a ✗ Unable to get list of installed Simulator runtimes. ! CocoaPods 1.11.3 out of date (1.13.0 is recommended). CocoaPods is a package manager for iOS or macOS platform code. Without CocoaPods, plugins will not work on iOS or macOS. For more info, see https://flutter.dev/to/platform-plugins To update CocoaPods, see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2023.3) • 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 17.0.10+0-17.0.10b1087.21-11572160) [✓] VS Code (version 1.92.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.94.0 [✓] Connected device (3 available) • V2164A (mobile) • 344393009600178 • android-arm64 • Android 11 (API 30) • macOS (desktop) • macos • darwin-x64 • macOS 14.6.1 23G93 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 128.0.6613.114 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. ```