Flutter Just Audio playbackEvent - flutter

I am using a package called Just Audio in my Flutter app. It provides an playBackEvent: playbackEvent.currentPosition which shows the time position that has been played in the Audio file. However I'm a little new to Dart and don't really understand how to subscribe a listener to this event so that I can do something with the changing values.
What I want to do is run a function which sets state when the value changes so I can show the progress and let the users know how far through the Audio file they are at that moment.
Can someone please explain to me how I should do this?
Any help would be much appreciated.

A complete sample available here.
StreamBuilder<Duration>(
stream: _player.durationStream,
builder: (context, snapshot) {
final duration = snapshot.data ?? Duration.zero;
return StreamBuilder<Duration>(
stream: _player.getPositionStream(),
builder: (context, snapshot) {
var position = snapshot.data ?? Duration.zero;
if (position > duration) {
position = duration;
}
return SeekBar(
duration: duration,
position: position,
onChangeEnd: (newPosition) {
_player.seek(newPosition);
},
);
},
);
},
),

Related

Can I Use "FutureBuilder()" under Void Method in Flutter

This is My Code.
Future<void> SendOrderDetails() async{
Row(
children: [
FutureBuilder(
future: topcart.getData(),
builder: (context, AsyncSnapshot<List<Cart>> snapshot) {
for(int i = 0; i<itemcount; i++)
{
if(itemcount>listModel2.data!.length) {
listModel2.data?.add(Model2(
ORDER_INFO_ID: 1,
PRODUCT_ED_ID: 2,
QTY: quantitycalcule.toString(),
UNIT_PRICE:'00',// snapshot.data![i].Book_initional_price!.toString(),
CHGED_BY:1,
CHGED_DATE: DateTime.now().toString(),
STATUS: 'P',
),);
}
}
return const Text('');
}
),
],
);
}
When I Call This, "FutureBuilder" did not run. I need "snapshot" in If condition. Please Help me.
I'm not sure what your code is trying to accomplish but there are a few things I can see that could be potentially causing issues:
You are calling FutureBuilder inside a Future and there is no await inside your future so it's really not going to work right.
The whole point of a FutureBuilder is to builds itself based on the latest snapshot of interaction with a Future. Maybe you can explain why this structure is the way it is.
topcart.getData() - Should not be in the future builder. You need to get something like
// This needs to be outside the build method, maybe initState()
Future<TYPE> _gd = topcart.get()
// Future Builder in the build method
FutureBuilder<TYPE>(
future: _gd,
builder: (BuildContext context, AsyncSnapshot<TYPE> snapshot) {});
Ideally, within the FutureBuilder() you want to check connection and data like:
if (snapshot.connectionState == ConnectionState.waiting) {
return // Progress indicator widget
} else if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return // Error Widget or Text
} else if (snapshot.hasData) {
return // Process data here
} else {
return // Empty set returned
}
} else {
return Text('State: ${snapshot.connectionState}');
}
this method returns nothing so you don't have way to check whether the future builder run or not, try to use print and check your debug console (or try to debug your code by using break points) if it works then do what ever you want to do
additional question: what state management you are using?
The whole point of FutureBuilder is to build (and so to return) a Widget based on a snapshot.
As it seems you don't need this Widget at all in your code, couldn't you just skip the Builder altogether ?
Something like this :
Future<void> SendOrderDetails() async {
var data = await topcart.getData();
for (int i = 0; i < itemcount; i++) {
if (itemcount > listModel2.data!.length) {
listModel2.data?.add(
Model2(
ORDER_INFO_ID: 1,
PRODUCT_ED_ID: 2,
QTY: quantitycalcule.toString(),
UNIT_PRICE: data![i].Book_initional_price!.toString(),
CHGED_BY: 1,
CHGED_DATE: DateTime.now().toString(),
STATUS: 'P',
),
);
}
}
}

Flutter: Video Player make app like instagram listview

I want to make an app like instagram in which response came from api which have images and videos but the issue is video player only play 1 video not a list of videos or each index of multiple videos so i dont know how to set it i tries it but could not work.
VideoPlayerController? _videoController;
late Future<void> _initializeVideoPlayerFuture;
void initState(){
super.initstate();
initialized();
}
void initialized(){ var result = await request.getCommunity(context, token!);
setState(() {
data = result;// result came from api in form of images and video and initialize the
videocontroller
_videoController=VideoPlayerController.network('https://wasisoft.com/dev/${data[1['media']}');
_initializeVideoPlayerFuture= _videoController!.initialize()..then((_) {
setState(() {
_videoController!.play();
});
});
});
after that inside listview.builder set a futurebuilder to set video player here it is...
FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return AspectRatio(
aspectRatio: _videoController!.value.aspectRatio,
child: VideoPlayer(_videoController!),
);
} else {
return Center(child: CircularProgressIndicator(),);
}
},
)
kindly any suggestion about this issue guide me i tried all solution related to it but could not found any helpful answer to resolve this issue.

Flutter auido_service bad internet connection

Good afternoon, please help with the audio_service plugin, I don't understand how to make a slider that won't move when audio is loaded with a bad Internet connection
StreamBuilder _timeLineSlider(double playbackSlider) {
return StreamBuilder<MediaState>(
stream: _mediaStateStream,
builder: (context, snapshot) {
final mediaState = snapshot.data;
_playEnded(
mediaState?.position.inSeconds ?? 0,
mediaState?.mediaItem?.duration?.inSeconds ?? 0
);
Duration _duration = mediaState?.position ?? Duration.zero;
return SeekBar(
duration: mediaState?.mediaItem?.duration ?? Duration.zero,
position: _duration.inSeconds > 0 ? _duration : Duration.zero,
onChangeEnd: AudioService.seekTo
);
}
); }
That's how I did it, but if the connection is bad, the slider moves while the audio doesn't play
I get a position like this
Stream<MediaState> get _mediaStateStream =>
Rx.combineLatest2<MediaItem?, Duration, MediaState>(
AudioService.currentMediaItemStream,
AudioService.positionStream,
(mediaItem, position) => MediaState(mediaItem, position));

Flutter background audio with progressbar

I want to play audio from a stream. I have used Just Audio for this. I want a progress bar like Audio Video Progress bar also play the audio in the background using Audio Service.
I have used the examples for all of them and they are working individually but I cannot concatenate them. would you please help with an example of how can I do it?
The example from audio_service plugin contains how to use audio_service along with just_audio. (combining 2 packages done)
Below is the mentioned SeekBar given in the example of the audio_service plugin.
// A seek bar.
StreamBuilder<MediaState>(
stream: _mediaStateStream,
builder: (context, snapshot) {
final mediaState = snapshot.data;
return SeekBar(
duration:
mediaState?.mediaItem?.duration ?? Duration.zero,
position: mediaState?.position ?? Duration.zero,
onChangeEnd: (newPosition) {
AudioService.seekTo(newPosition);
},
);
},
),
...
class SeekBar extends StatefulWidget {
final Duration duration;
final Duration position;
final ValueChanged<Duration>? onChanged;
final ValueChanged<Duration>? onChangeEnd;
SeekBar({
required this.duration,
required this.position,
this.onChanged,
this.onChangeEnd,
});
#override
_SeekBarState createState() => _SeekBarState();
}
// more code in the plugin example
Now from the above code, as you can see the example uses custom-designed SeekBar (which uses slider).
Instead of the custom slider, you can possibly use the plugin widget you wish. ProgressBar in your case.
StreamBuilder<MediaState>(
stream: _mediaStateStream,
builder: (context, snapshot) {
final mediaState = snapshot.data;
return ProgressBar(
total:
mediaState?.mediaItem?.duration ?? Duration.zero,
progress: mediaState?.position ?? Duration.zero,
onSeek: (newPosition) {
AudioService.seekTo(newPosition);
},
);
},
),
This is a change for the above SeekBar with ProgressBar.
(Combining 3rd package done)
Note: For the buffered. You can get the bufferedPosition from the audio_service PlaybackStateStream.
Edit:
The below is how I used it to add bufferedPosition.
(I changed the MediaState class, corresponding state getter a bit to achieve it)
StreamBuilder<MediaState>(
stream: _mediaStateStream,
builder: (context, snapshot) {
final mediaState = snapshot.data;
return ProgressBar(
total:
mediaState?.mediaItem?.duration ?? Duration.zero,
progress: mediaState?.position ?? Duration.zero,
buffered: mediaState?.playbackState?
.bufferedPosition ?? Duration.zero,
onSeek: (newPosition) {
AudioService.seekTo(newPosition);
},
);
},
),
...
Stream<MediaState> get _mediaStateStream =>
Rx.combineLatest3<MediaItem, Duration, PlaybackState, MediaState>(
AudioService.currentMediaItemStream,
AudioService.positionStream,
AudioService.playbackStateStream,
(mediaItem, position, playbackState) =>
MediaState(mediaItem, position, playbackState));
...
class MediaState {
final MediaItem mediaItem;
final Duration position;
final PlaybackState playbackState;
MediaState(this.mediaItem, this.position, this.playbackState);
}

StreamBuilder not updating ListView.builder after data changed in Flutter

I am new to Flutter and facing an issue with StreamBuilder & ListView.builder.
I am making a network call on click of a button(Apply Button) available in the list of the card, based on that other buttons are displayed.
the issue I am facing is that widgets are not updated after successful network call but, when I refresh the page I am getting updated result.
What I am doing wrong?
I am not Using any State into this. Do I need to use it?
Widget Code
StreamBuilder(
initialData: [],
stream: dataBoc.ListData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemBuilder: (BuildContext context, index) {
return InkWell(
key: Key(snapshot.data[index]["lid"]),
child: DataCard(
DataModel(snapshot.data[index]),
),
onTap: () {
Navigator.pushNamed(context, "/detailPage",
arguments: snapshot.data[index]["id"]);
},
);
},
itemCount: snapshot.data.length,
);
}
},
),
Bloc Code
//Here is how I am adding data to the stream
if (res.statusCode == 200) {
var data = json.decode(res.body);
if (data['status'] == true) {
// listDataStream.sink.add(data['result']);
listDataStream.add(data['result']);
} else {
listDataStream.sink.addError("Failed to Load");
}
}
Expected result: When I make Network call and if it succeeds then based on network result other buttons must be displayed on the appropriate card.
I have fixed this issue. The issue was my widget tree was not well structured and it was breaking the Widget build process.