ryanheise / audio_service

Flutter plugin to play audio in the background while the screen is off.
796 stars 476 forks source link

i have no idea how to set the _queue dynamicly from the demo, not final from create #110

Closed zhancheng closed 4 years ago

ryanheise commented 4 years ago

There is no reason why you couldn't do this with the APIs provided. You can call setQueue and pass in any parameter, which is not restricted to being a final list. You can write code to create any list and pass it in as the parameter.

zhancheng commented 4 years ago

@ryanheise i set the _queue at another function but still get null from onXXXX function, may u have a try.

ryanheise commented 4 years ago

If you're getting an error, please post the error (by the way, I have set this GitHub project up so that it asks you to fill in a template which includes all the information I need from you to address the issue. If you don't provide this information, I don't know how to help.)

zhancheng commented 4 years ago

@ryanheise https://gist.github.com/zhancheng/24c22aa58e4d22606e192fbb0453df2e this is my code

zhancheng commented 4 years ago

i set _queue in setPlayList() function also work from play() function but not works for @override onStart function

ryanheise commented 4 years ago

If you're getting an error, please post the error (by the way, I have set this GitHub project up so that it asks you to fill in a template which includes all the information I need from you to address the issue. If you don't provide this information, I don't know how to help.)

zhancheng commented 4 years ago

@ryanheise


import 'dart:async';

import 'package:audio_service/audio_service.dart';
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/material.dart';

MediaControl playControl = MediaControl(
  androidIcon: 'drawable/ic_action_play_arrow',
  label: 'Play',
  action: MediaAction.play,
);
MediaControl pauseControl = MediaControl(
  androidIcon: 'drawable/ic_action_pause',
  label: 'Pause',
  action: MediaAction.pause,
);
MediaControl stopControl = MediaControl(
  androidIcon: 'drawable/ic_action_stop',
  label: 'Stop',
  action: MediaAction.stop,
);

class AudioPlayerTask extends BackgroundAudioTask {
  List<MediaItem> _queue = [];
  int _queueIndex = 0;
  AudioPlayer _audioPlayer = new AudioPlayer();
  Completer _completer = Completer();
  int _position;

  bool get hasNext => _queueIndex + 1 < _queue.length;

  bool get hasPrevious => _queueIndex > 0;

  MediaItem get mediaItem => _queue[_queueIndex];

  void setPlayList(List<MediaItem> list){
    _queue = list;
  }

  AudioPlayerTask(this._queue);

  void play({List list, entry}){
    print(_queue); // this can be right
    AudioService.start(
      backgroundTaskEntrypoint: entry,
      resumeOnClick: true,
      androidNotificationChannelName: 'Audio Service Demo',
      notificationColor: 0xFF2196f3,
      androidNotificationIcon: 'mipmap/ic_launcher',
    );
  }

  @override
  Future<void> onStart() async {
    var playerStateSubscription = _audioPlayer.onPlayerStateChanged
        .where((state) => state == AudioPlayerState.COMPLETED)
        .listen((state) {
      _handlePlaybackCompleted();
    });
    var audioPositionSubscription =
    _audioPlayer.onAudioPositionChanged.listen((when) {
      final wasConnecting = _position == null;
      _position = when.inMilliseconds;
      if (wasConnecting) {
        _setPlayState();
      }
    });

    print(_queue); // this is empty

    AudioServiceBackground.setQueue(_queue);
    AudioServiceBackground.setMediaItem(mediaItem);
    _setState(state: BasicPlaybackState.connecting, position: 0);
    onPlay();
    await _completer.future;
    playerStateSubscription.cancel();
    audioPositionSubscription.cancel();
  }

  void _setPlayState() {
    _setState(state: BasicPlaybackState.playing, position: _position);
  }

  void _handlePlaybackCompleted() {
    if (hasNext) {
      onSkipToNext();
    } else {
      onStop();
    }
  }

  void playPause() {
    print(_queueIndex);
    if (AudioServiceBackground.state.basicState == BasicPlaybackState.playing)
      onPause();
    else
      onPlay();
  }

  @override
  void onSkipToNext() {
    if (!hasNext) return;
    if (AudioServiceBackground.state.basicState == BasicPlaybackState.playing) {
      _audioPlayer.stop();
    }
    _queueIndex++;
    _position = null;
    _setState(state: BasicPlaybackState.skippingToNext, position: 0);
    AudioServiceBackground.setMediaItem(mediaItem);
    onPlay();
  }

  @override
  void onSkipToPrevious() {
    if (!hasPrevious) return;
    if (AudioServiceBackground.state.basicState == BasicPlaybackState.playing) {
      _audioPlayer.stop();
      _queueIndex--;
      _position = null;
    }
    _setState(state: BasicPlaybackState.skippingToPrevious, position: 0);
    AudioServiceBackground.setMediaItem(mediaItem);
    onPlay();
  }

  @override
  void onPlay() {
    _audioPlayer.play(mediaItem.id);
    if (_position != null) {
      _setPlayState();
      // Otherwise we are still loading the audio.
    }
  }

  @override
  void onPause() {
    _audioPlayer.pause();
    _setState(state: BasicPlaybackState.paused, position: _position);
  }

  @override
  void onSeekTo(int position) {
    _audioPlayer.seek(position / 1000.0);
    final state = AudioServiceBackground.state.basicState;
    _setState(state: state, position: position);
  }

  @override
  void onClick(MediaButton button) {
    playPause();
  }

  @override
  void onStop() {
    _audioPlayer.stop();
    _setState(state: BasicPlaybackState.stopped);
    _completer.complete();
  }

  void _setState({@required BasicPlaybackState state, int position = 0}) {
    AudioServiceBackground.setState(
      controls: getControls(state),
      basicState: state,
      position: position,
    );
  }

  List<MediaControl> getControls(BasicPlaybackState state) {
    switch (state) {
      case BasicPlaybackState.playing:
        return [pauseControl, stopControl];
      case BasicPlaybackState.paused:
        return [playControl, stopControl];
      default:
        return [stopControl];
    }
  }
}

i use AudioPlayerTask audio = new AudioPlayerTask(playList) to set the list dynamicly , but at on start function it was still empty. i dont know how to do, much thanks!

ryanheise commented 4 years ago

I see, there's a miscommunication perhaps, but what I'm asking for is the error message. You already linked to the gist but that's not the error message. The error message is the output that you get when you attempt to run the app and it spits out error messages and hopefully including a stack trace with line numbers. Hopefully that clears up what I'm asking for when I ask for the error message.

zhancheng commented 4 years ago

@ryanheise there is no error message , just about the usage, i dont know how to set the queue from outside, i run my code, the "_queue" in the onStart function always be empty. i must set the queue when music playlist request done async, did i describe it clearly?

zhancheng commented 4 years ago

@ryanheise may u write a demo for request music list , much thanks!

ryanheise commented 4 years ago

If there is no error, I misunderstood. What did you mean when you wrote " set the _queue at another function but still get null from onXXXX function"? What line number did you get a null? Please reference the gist since that has line numbers.

zhancheng commented 4 years ago

@ryanheise line 85 to set queue, line 172 can not read the right queue.

ryanheise commented 4 years ago

Line 85 is never executed because it is inside of a method that you never call, which suggests you might benefit from asking for programming help on forums like Stackoverflow or Gitter rather than filing an issue with audio_service.

I will close this issue, and in future if you have an issue with this project, please open an issue using one of the provided templates.

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs, or use StackOverflow if you need help with audio_service.