栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

flutter 仿网易云音乐(2)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

flutter 仿网易云音乐(2)

gitee项目地址     github项目地址

如果喜欢请点点star

这里今天说一下项目的播放器选择

查看了一下pub.dev 上主流的播放器插件主要有audioplayers和just_audio

额外提一嘴android 和 ios 的配置

android

AndroidManifest.xml


    
    
    
    
    
    
    
    
    
    
   
        
            
            
            
            
            
                
                
            
        
        
          
            
          
        

        
          
            
          
         
        
        
    

ios



	
		CFBundleDevelopmentRegion
		$(DEVELOPMENT_LANGUAGE)
		CFBundleExecutable
		$(EXECUTABLE_NAME)
		CFBundleIdentifier
		$(PRODUCT_BUNDLE_IDENTIFIER)
		CFBundleInfoDictionaryVersion
		6.0
		CFBundleName
		仿网易云
		CFBundlePackageType
		APPL
		CFBundleShortVersionString
		$(FLUTTER_BUILD_NAME)
		CFBundleSignature
		????
		CFBundleVersion
		$(FLUTTER_BUILD_NUMBER)
		LSRequiresIPhoneOS
		
		UILaunchStoryboardName
		LaunchScreen
		UIMainStoryboardFile
		Main
		UISupportedInterfaceOrientations
		
			UIInterfaceOrientationPortrait
			UIInterfaceOrientationLandscapeLeft
			UIInterfaceOrientationLandscapeRight
		
		UISupportedInterfaceOrientations~ipad
		
			UIInterfaceOrientationPortrait
			UIInterfaceOrientationPortraitUpsideDown
			UIInterfaceOrientationLandscapeLeft
			UIInterfaceOrientationLandscapeRight
		
		UIViewControllerbasedStatusBarAppearance
		
		UIBackgroundModes
		
			audio
		
		NSAppTransportSecurity
		
			NSExceptionMinimumTLSVersion
  			TLSv1.0
			NSAllowsArbitraryLoads
    		
			NSAllowsArbitraryLoadsInWebContent
			
    		NSAllowsArbitraryLoadsForMedia
    		
		   	NSExceptionRequiresForwardSecrecy
            
            NSIncludesSubdomains
            
            NSTemporaryExceptionAllowsInsecureHTTPLoads
            
		
	

主要是http协议 至于ios的我也不懂 反正我配置了不得所以在网上瞎找了一下并且将网易云http改换成https才能播放,如果有哪位大哥懂的可以交流一下

两种播放器我都在本项目中使用过,一开始选择用audioplayers,操作也简便,但是考虑到搭配audio_service实现后台控制音乐,我琢磨了一段时间audioplayers发现我太会使用o(╥﹏╥)o,所以选择了与audio_service匹配的just_audio,通过audio_service的官方实例差不多可以使用,官方给的教程实例

根据官方文档的介绍需要安装的依赖有 just_audio、audio_service、get_it

创建目录 services、notifiers文件 page_manager.dart

先从services中先说service_locator.dart

// 初始化音频背景处理

import 'package:get_it/get_it.dart';
import '../page_manager.dart';
import 'audio_handler.dart';
import 'playlist_repository.dart';

GetIt getIt = GetIt.instance;
Future setupServiceLocator() async {
  getIt.registerSingleton(await initAudioService());
  getIt.registerLazySingleton(() => DemoPlaylist());
  getIt.registerLazySingleton(() => PageManager());
}

这里使用到了git_it包,主要是可以全局去控制,具体我也不懂,我也是看官方是咧

AudioPlayerHandler 第一个是创建audio_service

PlaylistRepository 第二是创建初始化的播放列表 主要是给后续加载缓存中的上次的播放列表 

PageManager 第三个是主要用于控制audio_service 和 just_audio播放音频

// 播放列表

import 'package:netease_app/model/songs.dart';

abstract class PlaylistRepository {
  Future>> fetchInitialPlaylist();
  Future fetchAnotherSong(Song song);
}

class DemoPlaylist extends PlaylistRepository {
  @override
  Future>> fetchInitialPlaylist(
      {int length = 3}) async {
    return [];
  }

  @override
  Future fetchAnotherSong(Song song) async {
    return song;
  }
}

这个就是 playlist_repository.dart

fetchInitialPlaylist 是用来初始化播放列表,这里暂时没有用到

fetchAnotherSong 是用来返回一个song音频文件

这里创建了一个song来保存每个音频文件 

// 构造class 歌曲

class Song {
  int id; // 歌曲id
  String name; // 歌曲名字
  String artists; // 艺术家
  String picUrl; // 歌曲图片
  Duration timer;
  Song(this.id, this.timer,
      {this.name = '', this.artists = '', this.picUrl = ''});
  Song.fromJson(Map json)
      : id = int.parse(json['id']),
        name = json['name'],
        artists = json['artists'],
        timer = Duration(milliseconds: int.parse(json["timer"])),
        picUrl = json['picUrl'];

  Map toJson() => {
        'id': id,
        'name': name,
        'artists': artists,
        'picUrl': picUrl,
        'timer': timer,
      };

  @override
  String toString() {
    return '{"id": "$id", "name": "$name", "artists": "$artists","picUrl": "$picUrl","timer": "${timer.inMilliseconds}"}';
  }
}

audio_handler.dart

首先说一下我理解到的逻辑  MediaItem 是指当前正在播放的歌曲 / queue 是指播放列表

所以当更新时需要修改mediaitem的参数 播放列表改变时需要改变queue列表

再说一下后台播放几个按钮对应触发的函数 播放 play()  pause()  seek() skipTonext()  skipToPrevious()  stop() 这几个最好不要在里面做其他的处理

由于官方的just_audio自带的下一首逻辑没有带有网易云的心动模式,所以没有用自带的

不用这个的还有一个原因就是这是我需要获取音频url,没办法直接setAudioSource,如果你们有更好的办法,也可以教教我

然后自定义了几个我需要用到的方法

abstract class AudioPlayerHandler implements AudioHandler {
  // 添加公共方法
  Future changeQueueLists(List list, {int index = 0});
  // 改变播放列表
  Future readySongUrl();
  // 获取歌曲url
  Future playIndex(int index);
  // 从下标播放
  Future addFmItems(List mediaItems, bool isAddcurIndex);
  // 私人fm
}

 这里初始化audio_service

Future initAudioService() async {
  return await AudioService.init(
    builder: () => MyAudioHandler(),
    config: AudioServiceConfig(
      androidNotificationChannelId: 'com.mycompany.myapp.audio',
      androidNotificationChannelName: '网易云音乐',
      androidNotificationOngoing: true,
      androidStopForegroundOnPause: true,
    ),
  );
}

然后创建自定义的audio_handler

class MyAudioHandler extends baseAudioHandler
    with SeekHandler
    implements AudioPlayerHandler {
  final _player = AudioPlayer(); // 播放器
  final _playlist = ConcatenatingAudioSource(children: []); // 播放列表
  final _songlist = []; // 这个是播放列表
  int _curIndex = 0; // 播放列表索引

  MyAudioHandler() {
    // 初始化
    // _loadEmptyPlaylist(); // 加载播放列表
    _notifyAudioHandleraboutPlaybackEvents(); // 背景状态更改
    _listenForDurationChanges(); // 当时间更改时更新背景
    _listenPlayEnd();
    // _listenForCurrentSongIndexChanges(); // 这个也是改背景
  }

  UriAudioSource _createAudioSource(MediaItem mediaItem) {
    return AudioSource.uri(
      Uri.parse(mediaItem.id),
      tag: mediaItem,
    );
  }

  Future _loadEmptyPlaylist() async {
    final session = await AudioSession.instance;
    await session.configure(AudioSessionConfiguration.speech());
    try {
      await _player.setAudioSource(_playlist);
    } catch (e) {
      print("错误:$e");
    }
  }

  void _listenPlayEnd() {
    _player.playerStateStream.listen((state) {
      if (state.playing) {
      } else {}
      switch (state.processingState) {
        case ProcessingState.idle:
          break;
        case ProcessingState.loading:
          break;
        case ProcessingState.buffering:
          break;
        case ProcessingState.ready:
          break;
        case ProcessingState.completed:
          skipTonext();
          break;
      }
    });
  }

  void _listenForDurationChanges() {
    // 当时间发送变化时(也就是意味着歌曲发送变化) 这个是更新时间
    _player.durationStream.listen((duration) {
      // final index = _player.currentIndex; // 当前播放下标
      final newQueue = queue.value;
      if (_curIndex == null || newQueue.isEmpty) return;
      final oldMediaItem = newQueue[_curIndex];
      final newMediaItem = oldMediaItem.copyWith(duration: duration);
      newQueue[_curIndex] = newMediaItem;
      queue.add(newQueue);
      mediaItem.add(newMediaItem);
    });
  }

  void _notifyAudioHandleraboutPlaybackEvents() {
    _player.playbackEventStream.listen((PlaybackEvent event) {
      final playing = _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,
        }[_player.processingState]!,
        shuffleMode: (_player.shuffleModeEnabled)
            ? AudioServiceShuffleMode.all
            : AudioServiceShuffleMode.none,
        playing: playing,
        updatePosition: _player.position,
        bufferedPosition: _player.bufferedPosition,
        speed: _player.speed,
        queueIndex: _curIndex,
      ));
    });
  }

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

  @override
  Future addQueueItems(List mediaItems) async {
    final audioSource = mediaItems.map(_futterSongItem);
    if (_songlist.length > 0) {
      // 判断当前歌曲的位置是否是处于最后一位

      _songlist.insertAll(_curIndex + 1, audioSource.toList());

      final newQueue = queue.value..insertAll(_curIndex + 1, mediaItems);
      // _curIndex++;
      queue.add(newQueue);
    } else {
      _songlist.insertAll(_curIndex, audioSource.toList());
      final newQueue = queue.value..insertAll(_curIndex, mediaItems);
      queue.add(newQueue);
    }
  }

  // 私人Fm的添加
  @override
  Future addFmItems(List mediaItems, bool isadd) async {
    final audioSource = mediaItems.map(_futterSongItem);
    if (_songlist.length > 0) {
      // 判断当前歌曲的位置是否是处于最后一位

      _songlist.insertAll(_curIndex + 1, audioSource.toList());

      final newQueue = queue.value..insertAll(_curIndex + 1, mediaItems);
      if (isadd) {
        _curIndex++;
      }
      queue.add(newQueue);
    } else {
      _songlist.insertAll(_curIndex, audioSource.toList());
      final newQueue = queue.value..insertAll(_curIndex, mediaItems);
      queue.add(newQueue);
    }
  }

  Song _futterSongItem(MediaItem mediaItem) {
    return Song(
      int.parse(mediaItem.id),
      mediaItem.duration!,
      artists: mediaItem.artist ?? '',
      picUrl: mediaItem.extras?["picUrl"] ?? '',
      name: mediaItem.title,
    );
  }

  @override
  Future changeQueueLists(List mediaitems,
      {int index = 0}) async {
    // 这里是替换播放列表
    final audioSource = mediaitems.map(_futterSongItem);
    // _playlist.clear();
    // _playlist.addAll(audioSource.toList()); // 添加到播放列表

    _songlist.clear();
    _songlist.addAll(audioSource.toList());
    _curIndex = index; // 更换了播放列表,将索引归0

    // notify system
    queue.value.clear();
    final newQueue = queue.value..addAll(mediaitems);
    queue.add(newQueue); // 添加到背景播放列表
  }

  @override
  Future playIndex(int index) async {
    // 接收到下标
    _curIndex = index;
    readySongUrl();
  }

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

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

  @override
  Future addQueueItem(MediaItem mediaItem) async {
    // manage Just Audio
    if (_songlist.length > 0) {
      // 判断当前歌曲的位置是否是处于最后一位
      _songlist.insert(_curIndex + 1, _futterSongItem(mediaItem));
      final newQueue = queue.value..insert(_curIndex + 1, mediaItem);
      _curIndex++;
      queue.add(newQueue);
    } else {
      _songlist.insert(_curIndex, _futterSongItem(mediaItem));
      final newQueue = queue.value..insert(_curIndex, mediaItem);
      queue.add(newQueue);
    }

    // notify system
  }

  @override
  Future readySongUrl() async {
    // 这里是获取歌曲url
    var song = this._songlist[_curIndex];
    String url = await getSongUrl({"id": '${song.id}'});
    if (url.isNotEmpty) {
      // 加载音乐
      url = url.replaceFirst('http', 'https');
      try {
        await _player.setAudioSource(AudioSource.uri(
          Uri.parse(url),
          tag: MediaItem(
            id: '${song.id}',
            title: song.name,
            artist: song.artists,
            duration: song.timer,
            artUri: Uri.parse(song.picUrl),
          ),
        ));
      } catch (e) {
        print('error======$e');
      }
      // 这里需要重新更新一次
      final playlist = queue.value;
      if (_curIndex == null || playlist.isEmpty) return;
      mediaItem.add(playlist[_curIndex]);

      play(); // 播放
    }
  }

  @override
  Future play() async {
    _player.play();
  }

  @override
  Future pause() => _player.pause();

  @override
  Future seek(Duration position) => _player.seek(position);

  @override
  Future skipTonext() async {
    // 当触发播放下一首
    if (_curIndex >= _songlist.length - 1) {
      _curIndex = 0;
    } else {
      _curIndex++;
    }
    // 然后触发获取url
    readySongUrl();
    final model = getIt();
    print('触发播放下一首');
    if (model.isPersonFm.value) {
      // 如果是私人fm
      print('私人fm========$_curIndex');
      if (_curIndex == _songlist.length - 1) {
        // 判断如果是最后一首
        print('触发');
        model.getPersonFmList();
      }
    }
  }

  @override
  Future skipToPrevious() async {
    if (_curIndex <= 0) {
      _curIndex = _songlist.length - 1;
    } else {
      _curIndex--;
    }
    readySongUrl();
  }

  @override
  Future stop() async {
    await _player.stop();
    return super.stop();
  }
}

_player 舒适化播放器 _playlist 这个已经废弃没有用到 _songlist 播放列表  _curIndex 播放索引

  MyAudioHandler() {
    // 初始化
    // _loadEmptyPlaylist(); // 加载播放列表
    _notifyAudioHandleraboutPlaybackEvents(); // 背景状态更改
    _listenForDurationChanges(); // 当时间更改时更新背景
    _listenPlayEnd();
    // _listenForCurrentSongIndexChanges(); // 这个也是改背景
  }

我就简单说说上面的代码有少许注释

readySongUrl    是我自定义的在play之前触发的加载音频url 

  @override
  Future readySongUrl() async {
    // 这里是获取歌曲url
    var song = this._songlist[_curIndex];
    String url = await getSongUrl({"id": '${song.id}'});
    if (url.isNotEmpty) {
      // 加载音乐
      url = url.replaceFirst('http', 'https');
      try {
        await _player.setAudioSource(AudioSource.uri(
          Uri.parse(url),
          tag: MediaItem(
            id: '${song.id}',
            title: song.name,
            artist: song.artists,
            duration: song.timer,
            artUri: Uri.parse(song.picUrl),
          ),
        ));
      } catch (e) {
        print('error======$e');
      }
      // 这里需要重新更新一次
      final playlist = queue.value;
      if (_curIndex == null || playlist.isEmpty) return;
      mediaItem.add(playlist[_curIndex]);

      play(); // 播放
    }
  }

如何在页面上控制播放

// 全局处理

import 'dart:async';

import 'package:audio_service/audio_service.dart';
import 'package:flutter/foundation.dart';
import 'package:netease_app/http/request.dart';
import 'package:netease_app/model/songs.dart';
import 'package:netease_app/notifiers/play_button_notifier.dart';
import 'package:netease_app/notifiers/play_item_notifier.dart';
import 'package:netease_app/notifiers/progress_notifier.dart';
import 'package:netease_app/services/audio_handler.dart';
import 'package:netease_app/services/playlist_repository.dart';
import 'package:netease_app/services/service_locator.dart';

class PageManager {
  final currentSongTitleNotifier = PlayItemNotifier();
  final playlistNotifier = ValueNotifier([]); // 播放列表
  final progressNotifier = ProgressNotifier(); // 时间进度条
  // final repeatButtonNotifier = RepeatButtonNotifier();
  final isFirstSongNotifier = ValueNotifier(true); // 是不是第一首歌
  final playButtonNotifier = PlayButtonNotifier();
  final isLastSongNotifier = ValueNotifier(true); // 是不是最后一首歌
  final isShuffleModeEnabledNotifier = ValueNotifier(false);
  final _audioHandler = getIt();
  final isPersonFm = ValueNotifier(false); // 当前是否是私人fm
  final waitPersonFm = ValueNotifier(false);

  // 初始化
  void init() async {
    await _loadPlaylist();
    _listenToChangesInPlaylist();
    _listenToPlaybackState();
    _listenToCurrentPosition();
    _listenToBufferedPosition();
    _listenToTotalDuration();
    _listenToChangesInSong();
  }

  Future _loadPlaylist() async {
    final songRepository = getIt();
    final playlist = await songRepository.fetchInitialPlaylist();
    final mediaItems = playlist
        .map((song) => MediaItem(
              id: song['id'] ?? '',
              album: song['album'] ?? '',
              title: song['title'] ?? '',
              extras: {'url': song['url']},
            ))
        .toList();
    _audioHandler.addQueueItems(mediaItems);
  }

  void _listenToChangesInPlaylist() {
    _audioHandler.queue.listen((playlist) {
      if (playlist.isEmpty) {
        playlistNotifier.value = [];
        currentSongTitleNotifier.value = MediaItem(id: '', title: '');
      } else {
        final newList = playlist;
        playlistNotifier.value = newList;
      }
      _updateSkipButtons();
    });
  }

  void _listenToPlaybackState() {
    // 监听播放状态
    _audioHandler.playbackState.listen((playbackState) {
      final isPlaying = playbackState.playing;
      final processingState = playbackState.processingState;
      print(processingState);
      if (processingState == AudioProcessingState.loading ||
          processingState == AudioProcessingState.buffering) {
        // 加载中
        playButtonNotifier.value = ButtonState.loading;
      } else if (!isPlaying) {
        // 没有播放
        playButtonNotifier.value = ButtonState.paused;
      } else if (processingState != AudioProcessingState.completed) {
        // 播放中
        playButtonNotifier.value = ButtonState.playing;
      } else if (isPlaying) {
        // playButtonNotifier.value = ButtonState.playing;
      } else {
        // 重置
        // print('重置触发');
        // _audioHandler.seek(Duration.zero);
        // _audioHandler.pause();
      }
    });
  }

  // 更新播放时间
  void _listenToCurrentPosition() {
    AudioService.position.listen((position) {
      // print('播放时间$position');
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: position,
        buffered: oldState.buffered,
        total: oldState.total,
      );
    });
  }

  // 更新缓冲位置
  void _listenToBufferedPosition() {
    _audioHandler.playbackState.listen((playbackState) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: playbackState.bufferedPosition,
        total: oldState.total,
      );
    });
  }

  // 更新总时长
  void _listenToTotalDuration() {
    _audioHandler.mediaItem.listen((mediaItem) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: oldState.buffered,
        total: mediaItem?.duration ?? Duration.zero,
      );
    });
  }

  // 更新歌曲显示最新的歌曲
  void _listenToChangesInSong() {
    _audioHandler.mediaItem.listen((mediaItem) {
      currentSongTitleNotifier.value = mediaItem!;
      print('Item$mediaItem');
      _updateSkipButtons();
    });
  }

  void _updateSkipButtons() {
    final mediaItem = _audioHandler.mediaItem.value;
    final playlist = _audioHandler.queue.value;
    if (playlist.length < 2 || mediaItem == null) {
      isFirstSongNotifier.value = true;
      isLastSongNotifier.value = true;
    } else {
      isFirstSongNotifier.value = playlist.first == mediaItem;
      isLastSongNotifier.value = playlist.last == mediaItem;
    }
    // if (isPersonFm.value) {
    //   // 如果这个是私人Fm的话 当播放的这首歌是最后一首歌的时候,遇到获取新的歌曲添加到歌单
    //   print(
    //       'object============${isLastSongNotifier.value}===========${waitPersonFm.value}');
    //   if (isLastSongNotifier.value && !waitPersonFm.value) {
    //     waitPersonFm.value = true;
    //     print('触发===============');
    //     this.getPersonFmList();
    //   }
    // }
  }

  // 改变是否是私人Fm
  void changeIsPersonFm(bool personFm) {
    isPersonFm.value = personFm;
  }

  // 获取私人Fm
  Future getPersonFmList() async {
    Map params = {
      "timestamp": '${DateTime.now().microsecondsSinceEpoch}',
    };
    getPersonaFm(params).then((value) {
      if (value["code"] == 200) {
        List playsongslist = [];
        value["data"].forEach((element) {
          playsongslist.add(Song(
            element["id"],
            Duration(milliseconds: element["duration"]),
            name: element["name"],
            picUrl: element["album"]["picUrl"],
            artists: createArtistString(element["artists"]),
          ));
        });
        addSongs(playsongslist);
      }
    });
  }

  createArtistString(List list) {
    List artistString = [];
    list.forEach((element) {
      artistString.add(element["name"]);
    });
    return artistString.join('/');
  }

  Future play() async {
    await _audioHandler.readySongUrl();
  }

  Future resumePlay() async {
    await _audioHandler.play();
  }

  sinkProgress(int timer) async {
    final oldState = progressNotifier.value;
    progressNotifier.value = ProgressBarState(
      current: Duration(milliseconds: timer),
      buffered: oldState.buffered,
      total: oldState.total,
    );
  }

  void pasue() {
    _audioHandler.pause();
  }

  void togglePlay() {
    if (playButtonNotifier.value == ButtonState.paused) {
      // 执行播放
      resumePlay();
    } else {
      // 执行暂停
      pasue();
    }
  }

  void playInex(int index) async {
    await _audioHandler.playIndex(index);
  }

  void seek(Duration position) => _audioHandler.seek(position); // 时间跳转
  void previous() => _audioHandler.skipToPrevious(); // 上一首
  void next() => _audioHandler.skipTonext(); // 下一首
  void repeat() {}
  void shuffle() {}
  // 添加一首歌
  Future add(Song song) async {
    final songRepository = getIt();

    final songitem = await songRepository.fetchAnotherSong(song);
    final mediaItem = MediaItem(
      id: songitem.id.toString(),
      album: '',
      artist: songitem.artists,
      duration: songitem.timer,
      title: songitem.name,
      artUri: Uri.parse(songitem.picUrl),
      extras: {
        'picUrl': songitem.picUrl,
      },
    );
    _audioHandler.addQueueItem(mediaItem);
  }

// 添加一个列表到播放列表
  Future addSongs(List songlist, {int index = 0}) async {
    final List mediaItems = [];
    songlist.forEach((element) {
      mediaItems.add(MediaItem(
        id: element.id.toString(),
        album: '',
        artist: element.artists,
        duration: element.timer,
        title: element.name,
        artUri: Uri.parse(element.picUrl),
        extras: {
          'picUrl': element.picUrl,
        },
      ));
    });
    await _audioHandler.addQueueItems(mediaItems);
  }

  Future changesonglistplay(List list, {int index = 0}) async {
    final List mediaItems = [];
    list.forEach((element) {
      mediaItems.add(MediaItem(
        id: element.id.toString(),
        album: '',
        artist: element.artists,
        duration: element.timer,
        title: element.name,
        artUri: Uri.parse(element.picUrl),
        extras: {
          'picUrl': element.picUrl,
        },
      ));
    });
    await _audioHandler.changeQueueLists(mediaItems, index: index);
  }

  void remove() {
    final lastIndex = _audioHandler.queue.value.length - 1;
    if (lastIndex < 0) return;
    _audioHandler.removeQueueItemAt(lastIndex);
  }

  Future changelist(list) async {}

  void dispose() {
    _audioHandler.customAction('dispose');
  }

  void stop() {
    _audioHandler.stop();
  }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/709034.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号