0

我正在构建运行一组音频的颤动音乐应用程序。我的应用程序的想法是在播放一个音频时我会收听它,当它完成时我将通过向 api 发送请求并获取歌曲 url 并再次播放来移动到下一个音频。

我为我的应用程序使用了两个颤振包just_audio来播放音频,并使用audio_service来处理后台播放和通知。

一切正常,直到我将移动屏幕关闭音频工作正常,完成后停止并且没有进入下一个时间。

和我的音频处理程序代码

Future<AudioHandler> initAudioService(player) async {
 return await AudioService.init(
builder: () => MyAudioHandler(player),
config: AudioServiceConfig(
    androidNotificationChannelId: 'com.mycompany.myapp.audio',
    androidNotificationChannelName: 'Audio Service Demo',
    androidNotificationOngoing: true,
    androidStopForegroundOnPause: false,
    androidNotificationIcon: 'mipmap/launcher_icon'),
    );
       }

class MyAudioHandler extends BaseAudioHandler {
final PlayerProvider playerProvider;

 MyAudioHandler(this.playerProvider) {
 _notifyAudioHandlerAboutPlaybackEvents();
_listenForDurationChanges();
_listenForCurrentSongIndexChanges();
_listenForSequenceStateChanges();
 }
 void _notifyAudioHandlerAboutPlaybackEvents() {
 playerProvider.player.playbackEventStream.listen((PlaybackEvent event) {
  final playing = playerProvider.player.playing;
  playbackState.add(playbackState.value.copyWith(
    controls: [
      MediaControl.skipToPrevious,
      if (playing) MediaControl.pause else MediaControl.play,
      MediaControl.stop,
      MediaControl.skipToNext,
    ],
    systemActions: const {
      MediaAction.seek,
    },
    androidCompactActionIndices: const [0, 1, 3],
    processingState: const {
      ProcessingState.idle: AudioProcessingState.idle,
      ProcessingState.loading: AudioProcessingState.loading,
      ProcessingState.buffering: AudioProcessingState.buffering,
      ProcessingState.ready: AudioProcessingState.ready,
      ProcessingState.completed: AudioProcessingState.completed,
    }[playerProvider.player.processingState],
    repeatMode: const {
      LoopMode.off: AudioServiceRepeatMode.none,
      LoopMode.one: AudioServiceRepeatMode.one,
      LoopMode.all: AudioServiceRepeatMode.all,
    }[playerProvider.player.loopMode],
    shuffleMode: (playerProvider.player.shuffleModeEnabled)
        ? AudioServiceShuffleMode.all
        : AudioServiceShuffleMode.none,
    playing: playing,
    updatePosition: playerProvider.player.position,
    bufferedPosition: playerProvider.player.bufferedPosition,
    speed: playerProvider.player.speed,
    queueIndex: event.currentIndex,
  ));
 });
}

void _listenForDurationChanges() {
playerProvider.player.durationStream.listen((duration) {
  var index = playerProvider.player.currentIndex;
  final newQueue = queue.value;
  if (index == null || newQueue.isEmpty) return;
  if (playerProvider.player.shuffleModeEnabled) {
    index = playerProvider.player.shuffleIndices[index];
  }
  final oldMediaItem = newQueue[index];
  final newMediaItem = oldMediaItem.copyWith(duration: duration);
  newQueue[index] = newMediaItem;
  queue.add(newQueue);
  mediaItem.add(newMediaItem);
});
}

 void listenForAudioFinished() {
 playerProvider.player.positionStream.listen((event) {
  Duration songDuration = playerProvider.player.duration ?? Duration.zero;
  StreamSubscription _subscription;
  bool done = false;
  // true if current player position >= song duration
  if (!(event.inSeconds < songDuration.inSeconds)) {
    done = true;
  } else {
    done = false;
  }
  if (done) {
    if (playerProvider.currentTrack != null &&
        playerProvider.nextTrack == false) {
      playerProvider.next(action: false);
    } else {
      playerProvider.nextTrack = false;
    }
    _subscription?.cancel();
  }
  });
  }

 void _listenForCurrentSongIndexChanges() {
  playerProvider.player.currentIndexStream.listen((index) {
  final playlist = queue.value;
  if (index == null || playlist.isEmpty) return;
  if (playerProvider.player.shuffleModeEnabled) {
    index = playerProvider.player.shuffleIndices[index];
  }
  mediaItem.add(playlist[index]);
  });
 }

  void _listenForSequenceStateChanges() {
  playerProvider.player.sequenceStateStream
    .listen((SequenceState sequenceState) {
  final sequence = sequenceState?.effectiveSequence;
  if (sequence == null || sequence.isEmpty) return;
  final items = sequence.map((source) => source.tag as MediaItem);
  queue.add(items.toList());
 });
}

@override
Future<void> addQueueItems(List<MediaItem> mediaItems) async {
// manage Just Audio
mediaItems.map(_createAudioSource);

 // notify system
 final newQueue = queue.value..addAll(mediaItems);
 queue.add(newQueue);
 }

 @override
 Future<void> addQueueItem(MediaItem mediaItem) async {
 final newQueue = queue.value..add(mediaItem);
 queue.add(newQueue);
 }

  UriAudioSource _createAudioSource(MediaItem mediaItem) {
  return AudioSource.uri(
  Uri.parse(mediaItem.extras['url']),
  tag: mediaItem,
  );
 }

@override
Future<void> removeQueueItemAt(int index) async {
 // manage Just Audio
 //_playlist.removeAt(index);

// notify system
final newQueue = queue.value..removeAt(index);
queue.add(newQueue);
}

@override
Future<void> play() => playerProvider.player.play();

@override
Future<void> pause() => playerProvider.player.pause();

@override
Future<void> seek(Duration position) async {
 playerProvider.seek(position);
}

@override
Future<void> skipToNext() => playerProvider.next();

@override
Future<void> skipToPrevious() => playerProvider.prev();

@override
Future customAction(String name, [Map<String, dynamic> extras]) async {
 if (name == 'dispose') {
  await playerProvider.player.dispose();
  super.stop();
  }
 }

@override
Future<void> stop() async {
  await playerProvider.player.stop();
  return super.stop();
  }
 }

在这里我播放任何音频的功能

final postData = {
      'user_id': userString == null ? 0 : user['id'],
      'part_id': _currentTrack.id,
      'session_id': userString == null ? null : user['sessionId']
    };
    final Response response = await _httpService.postRequest(url, postData);
    if (response.statusCode == 200 && response.data['status']) {
      final parsedData = response.data['listening_details'];
      if (parsedData['user_session'] == 'yes') {
        _session = true;
        if (parsedData['allow_hearing_part'] == 'yes') {
          _currentTrack.path = parsedData['path'];
          _playlist[index].path = parsedData['path'];
        }
      } else {
        _session = false;
        _currentTrack.path = null;
        _playlist[index].path = null;
      }
    }

    if (_currentTrack.path != null) {
      var tag = MediaItem(
        // Specify a unique ID for each media item:
        id: _currentTrack.id.toString(),
        // Metadata to display in the notification:
        album: Get.Get.locale.languageCode == 'en'
            ? _currentTrack.book['title_en']
            : _currentTrack.book['title'],
        title: Get.Get.locale.languageCode == 'en'
            ? _currentTrack.titleEn
            : _currentTrack.title,
        artUri:
            Uri.parse('${_currentTrack.image}'),
      );

      await player.setAudioSource(AudioSource.uri(
        Uri.parse(_currentTrack.path),
        tag: tag,
      ));

      _audioHandler.play();
      _audioHandler.playMediaItem(tag);
      _audioHandler.listenForAudioFinished();
      onAudioDone();
    }

    _isLoading = false;
    notifyListeners();
4

0 回答 0