suragch/streaming_audio_flutter_demo

Pass URL to Pagemanager from main page?

Closed this issue · 6 comments

How would you pass the URL to the Pagemanger from the main page?

Here's what I did based on this answer at Stackoverflow;

https://stackoverflow.com/questions/68055971/pass-a-string-to-a-class-in-flutter/68056327?noredirect=1#comment120287119_68056327

Is it worth committing it to the code?

Yes, that's one option, to pass the URL into the constructor of your state management class. Another option would be to have a method on the state management class that you call from the UI. You could either pass the URL in from there or just tell the state management class to retrieve the link from whatever service provides the audio URLs. I talk about this pattern a bit more here:

It might be worth updating this repo (and the accompanying tutorial). The tutorial focuses more on how to use just_audio rather than state management, but I'll leave this issue open for now. I am also working on another tutorial for audio_service and just_audio where I do I bit more with state management.

I may have been premature with the option to pass the URL into the constructor of the state management class. I was experiencing a lot of instability and noticed these errors below. So I will try the next option you suggested and let you know how it goes.

I/ExoPlayerImpl(15278): Init afdbbc4 [ExoPlayerLib/2.13.1] [taimen, Pixel 2 XL, Google, 30]
E/ExoPlayerImplInternal(15278): Playback error
E/ExoPlayerImplInternal(15278): com.google.android.exoplayer2.ExoPlaybackException: Source error
E/ExoPlayerImplInternal(15278): at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:579)
E/ExoPlayerImplInternal(15278): at android.os.Handler.dispatchMessage(Handler.java:102)
E/ExoPlayerImplInternal(15278): at android.os.Looper.loop(Looper.java:223)
E/ExoPlayerImplInternal(15278): at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal(15278): Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 403
E/ExoPlayerImplInternal(15278): at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:383)
E/ExoPlayerImplInternal(15278): at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:201)
E/ExoPlayerImplInternal(15278): at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
E/ExoPlayerImplInternal(15278): at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1015)
E/ExoPlayerImplInternal(15278): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415)
E/ExoPlayerImplInternal(15278): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/ExoPlayerImplInternal(15278): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/ExoPlayerImplInternal(15278): at java.lang.Thread.run(Thread.java:923)
E/AudioPlayer(15278): TYPE_SOURCE: Response code: 403
I/ExoPlayerImpl(15278): Release afdbbc4 [ExoPlayerLib/2.13.1] [taimen, Pixel 2 XL, Google, 30] [goog.exo.core]
E/flutter (15278): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: (0) Source error
E/flutter (15278): #0 AudioPlayer._load (package:just_audio/just_audio.dart:716:9)
E/flutter (15278):
E/flutter (15278): #1 AudioPlayer._setPlatformActive.setPlatform (package:just_audio/just_audio.dart:1096:28)
E/flutter (15278):

I'm sure this is not the best way to do it but it works; I basically repurposed the _init in the pagemanager class;

I added a small placeholder URL just for startup;

String url = "https://placeholder.m4a";

Then;

Future<String> seturl(url) async {
    _audioPlayer = AudioPlayer();
    await _audioPlayer.setUrl(url);
    _audioPlayer.playerStateStream.listen((playerState) {
      final isPlaying = playerState.playing;
      final processingState = playerState.processingState;
      if (processingState == ProcessingState.loading ||
          processingState == ProcessingState.buffering) {
        buttonNotifier.value = ButtonState.loading;
      } else if (!isPlaying) {
        buttonNotifier.value = ButtonState.paused;
      } else if (processingState != ProcessingState.completed) {
        buttonNotifier.value = ButtonState.playing;
      } else {
        _audioPlayer.seek(Duration.zero);
        _audioPlayer.pause();
      }
    });
    _audioPlayer.positionStream.listen((position) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: position,
        buffered: oldState.buffered,
        total: oldState.total,
      );
    });
    _audioPlayer.bufferedPositionStream.listen((bufferedPosition) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: bufferedPosition,
        total: oldState.total,
      );
    });

    _audioPlayer.durationStream.listen((totalDuration) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: oldState.buffered,
        total: totalDuration ?? Duration.zero,
      );
    });
    return url;
  }

Then I called it from the main page by doing;

_pageManager.seturl(mynewurl);

I just went through the tutorial again to make any needed updates. I reconsidered your solution to add a setUrl method in the page manager, but I decided for the sake of simplicity in the tutorial I wouldn't add that. However, I did add a comment to the tutorial recommending different options like the one you used.