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));
Related
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.
I have an null safety issue with my StreamBuilder in my flutter app.
On the open bracket "{" of the builder: property I am getting this error
The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
Here is the code for the StreamBuilder.
StreamBuilder (
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
I tried to add a type like this: StreamBuilder (
but I get this error: The argument type 'Stream<DocumentSnapshot<Map<String, dynamic>>>' can't be assigned to the parameter type 'Stream<QuerySnapshot<Object?>>?'.
Now I change the type to match the statement above and now I am back at the original error message. Here is what I changed the type to.
StreamBuilder <DocumentSnapshot<Map<String, dynamic>>>(
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
I don't know what is wrong or how to fix it. I know I need either this "!" or this "?" but I don't know which one or where to put it.
I would really appreciate some help here.
A StreamBuilder must return a Widget in its builder parameter. If you don't need to show any Widget (just do some background update), you can use a StreamSubscription instead:
class _MyWidgetState extends State<MyWidget> {
late final StreamSubscription<DocumentSnapshot> _subscription;
#override
void initState() {
super.initState();
final Stream<DocumentSnapshot> stream = _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots();
_subscription = stream.listen((data) {
if (data == null) return;
setState(() => clientFNameController.text = data['clientFName'] ?? "");
});
}
#override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
However, if you want to keep using StreamBuilder, you can
just return an empty Widget (not really a good practice):
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
}
return SizedBox.shrink();
},
),
return a meaningful Widget based on each operation:
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
return Text("client name updated");
}
return Text("client name not updated");
},
),
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);
}
I want to use await inside streambuilder. However, if you use async inside, you get an error. On the code below !!!!!!!! That's the part I want to solve. Thank you very much if I can tell you how.
class _MemoStreamState extends State<MemoStream> {
final _fireStore = Firestore.instance;
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _fireStore
.collection(widget.logInUsrEmail)
.orderBy('id', descending: false)
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return LinearProgressIndicator();
final memos = snapshot.data.documents;
List<MemoMaterial> memoList = [];
for (var memo in memos) {
final memoDocumentID = memo.documentID;
final memoTitle = await PlatformStringCryptor().decrypt(memo.data['title'], _key); !!!!!!!!!!
final memoUsrID = memo.data['usrID'];
final memoUsrPW = memo.data['usrPW'];
final memoText = memo.data['text'];
final memoCreateTime = memo.data['createTime'];
final memoMaterial = MemoMaterial(
logInUsrEmail: widget.logInUsrEmail,
doc: memoDocumentID,
title: memoTitle,
usrID: memoUsrID,
usrPW: memoUsrPW,
text: memoText,
createTime: memoCreateTime,
);
memoList.add(memoMaterial);
}
return Expanded(
child: new ListView.builder(
You should do something like this :
Stream<List<MemoMaterial>> memosStream;
Future<MemoMaterial> generateMemoMaterial(Memo memo) async {
final memoTitle =
await PlatformStringCryptor().decrypt(memo.data['title'], _key);
return MemoMaterial(
logInUsrEmail: widget.logInUsrEmail,
doc: memo.documentID,
title: memoTitle,
usrID: memo.data['usrID'],
usrPW: memo.data['usrPW'],
text: memo.data['text'];,
createTime: memo.data['createTime'],
);
}
#override
void initState() {
memosStream = _fireStore
.collection(widget.logInUsrEmail)
.orderBy('id', descending: false)
.snapshots()
.asyncMap((memos) => Future.wait([for (var memo in memos) generateMemoMaterial(memo)]));
super.initState();
}
#override
Widget build(BuildContext context) {
return StreamBuilder<List<MemoMaterial>>(
stream: memosStream // Use memostream here
asyncMap() will "transform" every new set of Documents into a list of MemoMaterial, and emit this list into the stream when the action is performed.
Future.wait() allows to perform multiple async requests simultaneously.
You can do it using FutureBuilder inside StreamBuilder in following way.
Stream<List<int>> callme() async* {
yield [1, 2, 3, 4, 5, 6];
}
buildwidget() async {
await Future.delayed(Duration(seconds: 1));
return 1;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: StreamBuilder(
stream: callme(),
builder: (_, sna) {
if (sna.hasData) {
return FutureBuilder(
future: buildwidget(),
builder: (_, snap) {
if (snap.hasData) {
return ListView.builder(
itemCount: sna.data.length,
itemBuilder: (_, index) {
return Text("${sna.data[index]} and ${snap.data}");
},
);
} else {
return CircularProgressIndicator();
}
},
);
} else {
return CircularProgressIndicator();
}
}),
),
);
}
I will prefer to use Getx or Provider State management to Handle the UI if it depends on the async function.
Suppose you want to fetch data from firebase using StreamBuilder() which returns some docs which contains image links then you want to download these images and show from storage. Obviously downloading the image is async type of work. Then you will get error if you show the images with the links you get direct from StreamBuilder().
What you can do is set a variable in getx or provider to show or hide the image Widget. If the Image is being downloaded or not downloaded then set the variable to hide/show the image when the async type of function is completed.
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);
},
);
},
);
},
),