I try to play video in flutter, and when i launch my code i have this problem
Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel., null, null)
This my code:
I create a class VideoApp extend statefulwidget.
_controller contain the video
import 'package:video_player/video_player.dart';
import 'package:flutter/material.dart';
void main() => runApp(VideoApp());
class VideoApp extends StatefulWidget {
#override
_VideoAppState createState() => _VideoAppState();
}
class _VideoAppState extends State<VideoApp> {
VideoPlayerController _controller;
#override
void initState() {
super.initState();
_controller = VideoPlayerController.network(
'http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4')
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Demo',
home: Scaffold(
body: Center(
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
Related
I'm working on a Flutterflow project and when I attempt to compile my widget inside of the custom widget section it returns multiple errors. Here is the code directly from pub.dev and I am adding the dependencies in the right section but I am continually getting the same errors.
import 'package:video_player/video_player.dart';
void main() => runApp(const VideoApp());
/// Stateful widget to fetch and then display video content.
class VideoApp extends StatefulWidget {
const VideoApp({Key? key}) : super(key: key);
#override
_VideoAppState createState() => _VideoAppState();
}
class _VideoAppState extends State<VideoApp> {
late VideoPlayerController _controller;
#override
void initState() {
super.initState();
_controller = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4')
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Demo',
home: Scaffold(
body: Center(
child: _controller.value.isInitialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
I'm working on this for more than 4hrs and am unable to make it through. What I'm trying to do is hide the keyboard when tapping outside the input focus area. Somehow the keyboard is unable to hide.
I tried all the possible answers on StackOverflow but was unable to find my solution.
Output: Keyboard persist even after search on google input
My Approach
// ignore_for_file: prefer_const_constructors
// ignore: use_key_in_widget_constructors
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter/services.dart';
void main(){
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Color(0xff1e2229)
));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body:WebViewClass()
),
);
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> {
bool isLoading = false;
final key = UniqueKey();
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
appBar: null,
body: SafeArea(
child: IgnorePointer(
ignoring: isLoading,
child: Stack(
children: [
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageFinished: (value) {
setState(() {
isLoading = false;
});
},
onPageStarted: (value) {
setState(() {
isLoading = true;
});
},
),
isLoading ? Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.grey.withOpacity(0.5),
child: const Center(child: CircularProgressIndicator()) ,
) : Container(),
],
),
)),));
}
}
It would be great if someone guide me on a way to resolve this issue.
Please use this code in initstate of stateful widget.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
According to the new flutter webview documentation:
Putting this piece of code inside the given full example will solve the keyboard dismiss the issue. Thanks to #khunt arpit
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
Full example code:
import 'dart:io';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewExample extends StatefulWidget {
#override
WebViewExampleState createState() => WebViewExampleState();
}
class WebViewExampleState extends State<WebViewExample> {
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
#override
Widget build(BuildContext context) {
return WebView(
initialUrl: 'https://flutter.dev',
);
}
}
I was happy bcs there was easy solution for flare package, but unfortunately now I have .riv format, so there is only rive package for me.
All examples I saw where playing animation instantly after screen loaded, but I need it to be started with function (button, onpressed etc).
class Animation extends StatefulWidget {
#override
_AnimationState createState() => _AnimationState();
}
class _AnimationState extends State<Animation> {
RiveAnimationController controller;
#override
void initState() {
super.initState();
controller = SimpleAnimation('Animation 1');
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: RiveAnimation.asset(
'match.riv',
controllers: [controller],
),
),
);
}
}
thank you in advance
From rive's official documentation, pass one more parameter to SimpleAnimation
class PlayPauseAnimation extends StatefulWidget {
const PlayPauseAnimation({Key? key}) : super(key: key);
#override
_PlayPauseAnimationState createState() => _PlayPauseAnimationState();
}
class _PlayPauseAnimationState extends State<PlayPauseAnimation> {
// Controller for playback
late RiveAnimationController _controller;
// Toggles between play and pause animation states
void _togglePlay() =>
setState(() => _controller.isActive = !_controller.isActive);
/// Tracks if the animation is playing by whether controller is running
bool get isPlaying => _controller.isActive;
#override
void initState() {
super.initState();
_controller = SimpleAnimation('Animation 1', autoplay: false);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RiveAnimation.network(
'match.riv',
controllers: [_controller],
// Update the play state when the widget's initialized
onInit: (_) => setState(() {}),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _togglePlay,
tooltip: isPlaying ? 'Pause' : 'Play',
child: Icon(
isPlaying ? Icons.pause : Icons.play_arrow,
),
),
);
}
}
I want to show images and videos in listview i am able show images but i want to show video also please help me . I want to create app like instagram here is my code for the video.
class mydynamic extends StatefulWidget {
#override
_mydynamicState createState() => _mydynamicState();
}
class _mydynamicState extends State<mydynamic> {
List<String> urls = [
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4",
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4",
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4"
];
VideoPlayerController _controller;
#override
void initState() {
super.initState();
_ controller = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4')
..initialize().then((_) {
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(title: Text("Adas")),
body: Center(
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
I have tried this above example which is working fine but i am not able to apply the logic for putting the videos in listview please any solution for this. Thank you
Use ListView.Builder with List<VideoPlayerController> of video controllers
class _mydynamicState extends State<mydynamic> {
List<String> urls = [
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4",
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4",
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4"
];
List<VideoPlayerController> _controllers = [];
#override
void initState() {
super.initState();
urls.forEach((element) {
_controllers.add(VideoPlayerController.network(element));
});
}
void _playVideos() {
_controllers.forEach((controller) {
controller
..initialize().then((_) {
setState(() {});
});
controller.value.isPlaying ? controller.pause() : controller.play();
});
}
bool isVideosPlaying() {
for (VideoPlayerController controller in _controllers) {
if (controller.value.isPlaying) {
return true;
}
}
return false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(title: Text("Adas")),
body: ListView.builder(
shrinkWrap: true,
itemBuilder: (ctx, index) {
VideoPlayerController controller = _controllers[index];
print(controller.value.isPlaying);
return Container(
child: controller.value.initialized
? AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: VideoPlayer(controller),
)
: Container(),
);
},
itemCount: urls.length,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_playVideos();
});
},
child: Icon(
isVideosPlaying() ? Icons.pause : Icons.play_arrow,
),
),
);
}
#override
void dispose() {
super.dispose();
_controllers.forEach((controller) {
controller.dispose();
});
}
}
I'm working on this flutter radio streaming app that currently works.I'm using AnimatedIcons.play_pause to start and stop the radio stream. Currently if I navigate to another page, the stream will keep playing. I'd like to stop the streaming (without using the pause button) when I navigate to another page. The reason is when you return back to the streaming page ... the page has reset back to the play buttonbool isPlaying = false;
but the stream is still on and so pressing the play button will result in 2 streams playing.
Here's the full code below:
import 'dart:async';
import 'package:flutter_radio/flutter_radio.dart';
void main() => runApp(HarvestRadio());
class HarvestRadio extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<HarvestRadio>
with SingleTickerProviderStateMixin {
String url = "https://fm898.online/mystream.mp3";
AnimationController _animationController;
bool isPlaying = false;
#override
void initState() {
super.initState();
audioStart();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
}
#override
void dispose() {
super.dispose();
_animationController.dispose();
}
Future<void> audioStart() async {
await FlutterRadio.audioStart();
print('Audio Start OK');
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Harvest Radio Online',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Harvest Radio Online '),
backgroundColor: Colors.blue,
centerTitle: true,
),
body: Container(
color: Colors.blueGrey.shade900,
child: Column(
children: <Widget>[
Expanded(
flex: 7,
child: Icon(
Icons.radio, size: 250,
color: Colors.lightBlue,
),
),
Material(
color: Colors.blueGrey.shade900,
child: Center(
child: Ink(
decoration: const ShapeDecoration(
color: Colors.lightBlue,
shape: CircleBorder(),
),
child: IconButton(
color: Colors.blueGrey.shade900,
iconSize: 67,
icon: AnimatedIcon(
icon: AnimatedIcons.play_pause,
progress: _animationController,
),
onPressed: () => _handleOnPressed(),
),
),
),
),
SizedBox(height: 50,)
],
),
),
));
}
void _handleOnPressed() {
setState(() {
FlutterRadio.play(url: url);
isPlaying = !isPlaying;
isPlaying
? _animationController.forward()
: _animationController.reverse();
});
}
}
Any help is much appreciated ... Thank you!
I had a similar situation, and ended up extending the routeObserver to know the users state all time:
the routeObserver.dart:
import 'package:flutter/material.dart';
class RouteObserverUtil extends RouteObserver<PageRoute<dynamic>> {
RouteObserverUtil({this.onChange});
final Function onChange;
void _sendScreenView(PageRoute<dynamic> route) {
String screenName = route.settings.name;
onChange(screenName);
}
#override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
super.didPush(route, previousRoute);
if (route is PageRoute) {
_sendScreenView(route);
}
}
#override
void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute is PageRoute) {
_sendScreenView(newRoute);
}
}
#override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
super.didPop(route, previousRoute);
if (previousRoute is PageRoute && route is PageRoute) {
_sendScreenView(previousRoute);
}
}
}
and here is a usage example:
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:myApp/utils/routeObserver.dart';
class _RouterScreenState extends State<RouterScreen> {
RouteObserverUtil _routeObserver;
#override
void initState() {
super.initState();
_routeObserver = RouteObserverUtil(onChange: _onChangeScreen);
}
void _onChangeScreen(String screen) {
SchedulerBinding.instance.addPostFrameCallback((_) {
print("changed to screen: " + screen);
});
}
...
}
I found a simple solution by wrapping my MaterialApp with WillPopScope ...Here's the code:
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onBackPressed,
child: MaterialApp(
title: 'Harvest Radio Online',
home: Scaffold(
appBar: AppBar(
title: const Text('Harvest Radio Online '),
backgroundColor: Colors.blue,
centerTitle: true,
),
Then the function for _onBackPressed:
Future<bool>_onBackPressed(){
FlutterRadio.stop();
Navigator.pop(
context, MaterialPageRoute(builder: (_) => Media()));
}
I also had to add the Navigator route back to the previous page.
I know it's a bit of a hack but it works. Thank you all!