我正在尝试将 Chewie flutter 包实现到我的应用程序中,我把所有内容都记录下来并使其尽可能可定制。它符合要求,但是当我在网络、andriod 或任何可能的设备上运行它时,我得到的只是这个加载屏幕:
这是我的代码:
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
import 'package:chewie/chewie.dart';
import 'package:video_player/video_player.dart';
import 'dart:io';
class ChewieVideoPlayer extends StatefulWidget {
ChewieVideoPlayer({
Key? key,
this.width,
this.height,
this.videoPath,
this.videosList,
this.isAutoPlay,
this.isLooping,
this.hideControlsAfter,
this.currentPlayIndex,
this.startTime,
this.videoPlatform,
this.hideControls,
this.aspectRatio,
this.disableFullScreen,
this.isLive,
this.disableZoomAndPan,
this.hideOptions,
this.allowScreenSleep,
this.disableMuting,
this.disablePlaybackSpeedChanging,
this.disableAutoInitialize,
this.fullScreenByDefault,
this.playbackSpeedList,
this.progressIndicatorDelay,
this.nonDraggableProgressBar,
}) : super(key: key);
final double? width;
final double? height;
final String? videoPath;
final List<String>? videosList;
final bool? isAutoPlay;
final bool? isLooping;
final int? hideControlsAfter;
int? currentPlayIndex;
final double? startTime;
final String? videoPlatform;
final bool? hideControls;
final double? aspectRatio;
final bool? disableFullScreen;
final bool? isLive;
final bool? disableZoomAndPan;
final bool? hideOptions;
final bool? allowScreenSleep;
final bool? disableMuting;
final bool? disablePlaybackSpeedChanging;
final bool? disableAutoInitialize;
final bool? fullScreenByDefault;
final List<double>? playbackSpeedList;
final int? progressIndicatorDelay;
final bool? nonDraggableProgressBar;
@override
State<ChewieVideoPlayer> createState() => _ChewieVideoPlayerState();
}
class _ChewieVideoPlayerState extends State<ChewieVideoPlayer> {
TargetPlatform? _platform;
late VideoPlayerController _videoPlayerController1;
late VideoPlayerController _videoPlayerController2;
ChewieController? _chewieController;
late List<String> srcs;
//Initializing the widget state
@override
void initState() {
super.initState();
initializePlayer();
/* srcs = widget.videosList ??
[
widget.videoPath ??
'https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4']; */
srcs = [
'https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4'
];
}
//Function to clear the memory to avoid leaks
@override
void dispose() {
_videoPlayerController1.dispose();
_videoPlayerController2.dispose();
_chewieController?.dispose();
super.dispose();
}
//Function to initialize the player
Future<void> initializePlayer() async {
_videoPlayerController1 = VideoPlayerController.networkUrl(
Uri.parse(srcs[widget.currentPlayIndex ?? 0]));
_videoPlayerController2 = VideoPlayerController.networkUrl(
Uri.parse(srcs[widget.currentPlayIndex ?? 0]));
await Future.wait([
_videoPlayerController1.initialize(),
_videoPlayerController2.initialize()
]);
_createChewieController();
setState(() {});
}
//Function that creates ChewieController and custmoize it (e.g. set color, autoplay, looping,etc)
void _createChewieController() {
// Check if videoPlatform is provided and set the platform accordingly
if (widget.videoPlatform != null) {
switch (widget.videoPlatform) {
case 'android':
_platform = TargetPlatform.android;
break;
case 'ios':
_platform = TargetPlatform.iOS;
break;
case 'windows':
_platform = TargetPlatform.windows;
break;
default:
// Handle other cases or leave platform as null
break;
}
}
final subtitles = [
Subtitle(
index: 0,
start: Duration.zero,
end: const Duration(seconds: 10),
text: const TextSpan(
children: [
TextSpan(
text: 'Hello',
style: TextStyle(color: Colors.red, fontSize: 22),
),
TextSpan(
text: ' from ',
style: TextStyle(color: Colors.green, fontSize: 20),
),
TextSpan(
text: 'subtitles',
style: TextStyle(color: Colors.blue, fontSize: 18),
)
],
),
),
Subtitle(
index: 0,
start: const Duration(seconds: 10),
end: const Duration(seconds: 20),
text: 'Whats up? :)',
),
];
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
autoPlay: widget.isAutoPlay ?? false,
looping: widget.isLooping ?? false,
hideControlsTimer: Duration(seconds: widget.hideControlsAfter ?? 3),
showControls: widget.hideControls ?? true,
startAt: widget.startTime != null
? Duration(milliseconds: (widget.startTime! * 1000).toInt())
: null,
aspectRatio: widget.aspectRatio ?? 1.7,
allowFullScreen: !(widget.disableFullScreen ?? false),
isLive: widget.isLive ?? false,
zoomAndPan: !(widget.disableZoomAndPan ?? false),
showOptions: !(widget.hideOptions ?? false),
allowedScreenSleep: widget.allowScreenSleep ?? false,
allowMuting: !(widget.disableMuting ?? false),
allowPlaybackSpeedChanging:
!(widget.disablePlaybackSpeedChanging ?? false),
autoInitialize: !(widget.disableAutoInitialize ?? false),
fullScreenByDefault: widget.fullScreenByDefault ?? false,
draggableProgressBar: !(widget.nonDraggableProgressBar ?? false),
playbackSpeeds:
widget.playbackSpeedList ?? [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
progressIndicatorDelay: widget.progressIndicatorDelay != null
? Duration(milliseconds: (widget.progressIndicatorDelay!))
: null,
additionalOptions: (context) {
return <OptionItem>[
OptionItem(
onTap: toggleVideo,
iconData: Icons.live_tv_sharp,
title: 'Next Video',
),
];
},
subtitle: Subtitles(subtitles),
subtitleBuilder: (context, dynamic subtitle) => Container(
padding: const EdgeInsets.all(10.0),
child: subtitle is InlineSpan
? RichText(
text: subtitle,
)
: Text(
subtitle.toString(),
style: const TextStyle(color: Colors.black),
),
),
);
}
//Function to switch to the next video in list
Future<void> toggleVideo() async {
await _videoPlayerController1.pause();
widget.currentPlayIndex = (widget.currentPlayIndex ?? 0) + 1;
if (widget.currentPlayIndex! >= srcs.length) {
widget.currentPlayIndex = 0;
}
await initializePlayer();
}
//Building the widget
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: AppTheme.light.copyWith(
platform: _platform ?? Theme.of(context).platform,
),
home: Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: _chewieController != null && _chewieController!
.videoPlayerController.value.isInitialized
? Chewie(controller: _chewieController!,)
const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 20),
Text('Loading'),
],
),
),
),
],
),
),
);
}
}
// Theme
class AppTheme {
static final light = ThemeData(
brightness: Brightness.light,
useMaterial3: true,
colorScheme: const ColorScheme.light(secondary: Colors.red),
disabledColor: Colors.grey.shade400,
visualDensity: VisualDensity.adaptivePlatformDensity,
);
static final dark = ThemeData(
brightness: Brightness.dark,
colorScheme: const ColorScheme.dark(secondary: Colors.red),
disabledColor: Colors.grey.shade400,
useMaterial3: true,
visualDensity: VisualDensity.adaptivePlatformDensity,
);
}
所以我尝试下载该应用程序,在网络上运行它,在andriod studio上运行它,等等,但没有希望。 我期望简单地让视频播放器播放 videoList(如果它不为空),如果它为空,那么它将使用 videoPath 作为其第一个条目并播放该视频。 我试图删除所有这些逻辑,而是对视频进行硬编码,并尝试了 Chewie 官方文档中使用的几种不同的逻辑,但没有希望。
如果有人能找出可能导致此问题的原因,我将非常感谢您。如果我没记错的话,这可能是我在 ChatGPT 上花了 8 个小时尝试调试它之后遇到的第一个 StackOverFlow 问题,哈哈。
第1步: 在 android>app>build.gradle 中更改compileSdkVersion
来自
compileSdkVersion flutter.compileSdkVersion
至
compileSdkVersion 34
compileSdkVersion 是在构建过程中编译您的应用程序的 Android SDK 版本。它决定了您可以在代码中使用的 API 和功能集。
所以根据最新版本的chewie包你至少需要compileSdkVersion 24
第2步:添加互联网权限(在debug模式下无需权限即可工作,但在release或debug apk中,如果Android Manifest文件中未添加权限,则不会进行网络调用)
转到 android>app>main>AndroidManifest.xml
<manifest xlmns:android...>
...
<uses-permission android:name="android.permission.INTERNET" /> //TODO: Add this line
<application ...
</manifest>
第3步:在调用initializePlayer之前初始化您的源(srcs)
void initState() {
super.initState();
//TODO: Initialize srcs before initializePlayer()
srcs = [
'https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4'
];
initializePlayer();
// /* srcs = widget.videosList ??
// [
// widget.videoPath ??
// 'https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4']; */
// srcs = [
// 'https://assets.mixkit.co/videos/preview/mixkit-daytime-city-traffic-aerial-view-56-large.mp4'
// ];
}