I have a flutter camera app and am able to get a recorded video to play. The problem is, I am only able to get it to play when a button is pressed. How do I get the code to run when the widget(screen) is created instead of when the button is pressed so I don't have to press a button to get it to play? Here is my code:
Here is the code for when the button is pressed:
//raised button
RaisedButton(
onPressed: () {stopButtonPressed();},
//stopButtonPressed
void stopButtonPressed() {
print('stopButtonPressed hit');
stopVideoRecording().then((_) {
print('StopVideoRecording complete');
});
}
//stopVideoRecording
Future<void> stopVideoRecording() async {
print('stopVideoRecording hit');
await _startVideoPlayer();
}
//_startVideoPlayer
Future<void> _startVideoPlayer() async {
print('_startVideoPlayer hit');
print(Provider.of<SendDataModel>(context, listen: false).displayImageVideo());
final VideoPlayerController vcontroller =
VideoPlayerController.file(File(Provider.of<SendDataModel>(context, listen: false).displayImageVideo()));
videoPlayerListener = () {
if (videoController != null && videoController.value.size != null) {
if (mounted) setState(() {});
videoController.removeListener(videoPlayerListener);
}
};
vcontroller.addListener(videoPlayerListener);
await vcontroller.setLooping(true);
await vcontroller.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
//saveImagePath = null;
videoController = vcontroller;
});
}
await vcontroller.play();
} //startVideoPlayer
Thanks!
You can call the function from initState(). initState() is called only once when the StatefulWidget is inserted into the Widget tree, so it's a good place to initialize variables or do what you're trying to do.
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
// Do anything you need done here
_startVideoPlayer();
// If you want a slight delay, use Future.delayed
Future.delayed(Duration(seconds: 1), (){
_startVideoPlayer();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
// rest of app
Related
I want to call a loading screen widget that has a column with an image, a text and a loading indicator, 5 seconds after the screen is built there should called a setState-method that changes a boolean value[foundOpponent] and with that the screen (the text should be changed into "found opponent" and the indicator into an Icon) after that there should be a delay of 2 seconds and then a Navigator.push to another screen.
I have already looked at https://stackoverflow.com/questions/49466556/flutter-run-method-on-widget-build-complete and tried most of the explained methods and it somewhat worked but the screen of the virtual phone was extremely lagging , the image that should get built in the build method does not even get displayed and while the image is loading the method that should get called after the build is being executed.
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
sleep(const Duration(seconds: 10));
setState(() {
foundOpponent = true;
});
sleep(const Duration(milliseconds: 2500));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const QuestionMainPage()),
);
});
}
I've tried the following methods:
WidgetsBinding.instance
.addPostFrameCallback((_) => yourFunction(context));
SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
}
Future<void> _runsAfterBuild() async {
await Future((){}); // <-- Dummy await
// This code runs after build
}
#override
Widget build(BuildContext context) {
_runsAfterBuild();
return Container();
}
Try using Future.delayed and make sure to put await
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await Future.delayed(Duration(seconds: 10));
//await task a
await Future.delayed(Duration(seconds: 1));
//await task B
});
}
I need to hide button after 1 mins but while reloading and again restarting application it will not show again once it hide it will not repeated
Use shared_preferences (or any persist memory) to persist the state of the button over restarts.
See Store key-value data on disk for details.
You need to use db to handle restarting application case.
You can use shared_preferences to store a flag about visibility.
class _GState extends State<G> {
static const String _buttonVisibilityKey = "DoneWIthButtonX";
bool showButton = false;
#override
void initState() {
super.initState();
_buttonActionChecker().then((value) async {
// return false if button never showed up, activate the timer to hide
print(value);
if (!value) {
showButton = true;
setState(() {});
Future.delayed(Duration(minutes: 1)).then((value) async {
showButton = false;
SharedPreferences.getInstance()
.then((value) => value.setBool(_buttonVisibilityKey, true));
setState(() {});
});
}
});
}
#override
void dispose() {
super.dispose();
}
/// is the button have been shown already return true
Future<bool> _buttonActionChecker() async {
return SharedPreferences.getInstance().then((value) {
return value.getBool(_buttonVisibilityKey) ?? false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: showButton
? FloatingActionButton(
onPressed: () {
setState(() {});
},
)
: null,
);
}
}
I'm developing an iOS app in Flutter, using a package called audio_service.
I use AudioServiceBackground.serQueue() to set multiple MediaItem to a Queue.
In the UI part, I'm trying to use AudioService.currentMediaItemStream to display the information of the currently playing media item.
When the first song in the queue is finished, the second song will be played. However, the information on the current media item does not change.
How do I detect that the song playing in the Queue has changed?
class AudioServiceScreen extends StatefulWidget {
#override
_AudioServiceScreenState createState() => _AudioServiceScreenState();
}
class _AudioServiceScreenState extends State<AudioServiceScreen> {
#override
void initState() {
super.initState();
Future(() async {
await AudioService.connect();
await start();
});
}
#override
void dispose() {
Future(() async {
await AudioService.disconnect();
});
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: ///,
body: StreamBuilder<MediaItem?>(
stream: AudioService.currentMediaItemStream,
builder: (context, snapshot) {
final mediaItem = snapshot.data;
},
),
);
}
Future<dynamic> start() async {
final success = await AudioService.start(
backgroundTaskEntrypoint: _backgroundTaskEntrypoint,
);
if (success) {
await updateQueue();
}
}
Future<void> updateQueue() async {
final queue = await getMediaLibrary(); // get data from FireStore
await AudioService.updateQueue(queue);
}
}
void _backgroundTaskEntrypoint() {
AudioServiceBackground.run(() => AudioPlayerTask());
}
class AudioPlayerTask extends BackgroundAudioTask {
final AudioPlayer audioPlayer = AudioPlayer();
#override
Future<void> onStart(Map<String, dynamic>? params) async {
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.speech());
await AudioServiceBackground.setState(
controls: [MediaControl.pause, MediaControl.stop],
playing: false,
processingState: AudioProcessingState.connecting,
);
}
#override
Future<void> onUpdateQueue(List<MediaItem> queue) async {
await AudioServiceBackground.setQueue(queue);
try {
await audioPlayer.setAudioSource(ConcatenatingAudioSource(
children:
queue.map((item) => AudioSource.uri(Uri.parse(item.id))).toList(),
));
} on Exception catch (e) {
await onStop();
}
}
}
Try read the docs and follow some of the example there. Because on "Background Code" section, there is "on Start" code. Maybe that code can help you out. I am sorry I cannot help you that much. I never try that package.
I am checking the connectivity using Connectivity().checkConnectivity() it is working but the setState() is not calling when I navigate to this page.
To navigate to main page to another page I am using Navigator.push(context, MaterialPageRoute(builder: (context) => search()));
and here is my next page
class search extends StatefulWidget {
#override
_searchState createState() => _searchState();
}
class _searchState extends State<search> {
List<filter> _list = [];
List<filter> to_display = [];
bool isoffline;
Future<void> connectivity() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
// I am connected to a mobile network.
setState(() {
isoffline = true;
});
print("connected");
} else if (connectivityResult == ConnectivityResult.wifi) {
setState(() {
isoffline = true;
});
// I am connected to a wifi network.
print("connected");
} else {
setState(() {
isoffline = false;
});
print(
"dissconneteddsfffffffffffffffffffffffffffffffffffffffffffffffffffffffdsfsd");
}
}
Future _future;
#override
void initState() {
mylist().then((value) {
setState(() {
_list = to_display = value;
});
});
connectivity();
print("value${isoffline}"); // this value is on null
_future = data();
super.initState();
}
print("value${isoffline}"); // this value is on null
The function connectivity is an asynchronous function. You are calling the function and immediately checking the boolean value, that's why you are getting null. You have to wait till the execution, either by using await or then syntax.
connectivity().then((value) {
print("value ${isoffline}");
});
In your code connectivity(); method is async which mean it will require some time to complete.
Now when init method is called it executes connectivity(); and then immediately executes print("value${isoffline}"); now the value for isoffline initially is null, hence null printed
solution is either you put print("value${isoffline}"); in connectivity(); method or try to add it after build method.
#override
Widget build(BuildContext context) {
connectivity();
print("value${isoffline}");
return YourWidget();
}
This ShakePlugin is not working with this piece of code,when im just using this code without these api calls and all its working fine.
class MyAppState extends State<MyApp> {
List data;
String _search = 'nature';
int index = 0;
File imageFile;
String imageData;
bool dataLoaded;
var path;
int count = 10;
FlutterShakePlugin _shakePlugin;
void initState() {
super.initState();
_shakePlugin = FlutterShakePlugin(
onPhoneShaken: () {
setState(() {
count=count+10;
});
},
},
)..startListening();
}
void dispose() {
super.dispose();
_shakePlugin.stopListening();
}
Future<String> getjsondata() async {
try {
var response = await http.get(
'https://api.unsplash.com/search/photos?per_page=${count}&client_id=TcAQEO3JoMG90U7Rl-YUiDo1x9XbZukzMOMQhxUVCV4&query=${_search}');
setState(() {
var converted = json.decode(response.body);
data = converted['results'];
});
} catch (e) {}
return 'success';
}
void saveImage(int i) async {
var url = data[i]['urls']['small'].toString();
var imageId = await ImageDownloader.downloadImage(url);
path = await ImageDownloader.findPath(imageId);
}
#override
Widget build(BuildContext context) {
getjsondata();
return GestureDetector(
child: SwipeDetector(
child: Container(
child: Image.network(
data[index]['urls']['small'],
I want to increase the count of images i recieve from api on shake of screen but this is not working even if i have installed all the libraries and all.
Calling your getjsondata method in the build method will cause the ui to render infinitely because you're calling setState in getjsondata. I think the shake plugin is working fine but its result is void because the screen is in an infinite render state.
If you move getjsondata to a FutureBuilder, remove the setState call from inside the getjsondata method and render your ui on the result of the Future your code should work.