alexmercerind / flutter_media_metadata

A Flutter plugin to read 🔖 metadata of 🎵 media files. Supports Windows, Linux, macOS, Android, iOS & Web.
MIT License
70 stars 40 forks source link

value invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed error om Isolate #39

Closed mohhamad-esmaili closed 3 weeks ago

mohhamad-esmaili commented 3 weeks ago

Hi I am using flutter_media_metadata: ^1.0.0+1 and i got error like

 Error processing file: G:\Music\01 Never Stop.mp3, Error: Bad state: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed.

well the matter is when i use package its fine on main thread but when i use it on other thread and Isolate i get this error, im solving this problem on other thread because the process for loading is too long and if you have a big archive of music like me, its not good experience to wait and freeze music player, so im glad to hear your solution, by the way here is my code:

  List<FileSystemEntity> _allMusicFiles = []; 
  int _currentOffset = 0; 

  Future<Map<String, List<MusicModel>>> loadMoreMusicFiles(
      {int limit = 20}) async {
    final startTime = DateTime.now();

    if (_currentOffset >= _allMusicFiles.length) {
      return {}; 
    }

    int end = _currentOffset + limit;
    List<FileSystemEntity> filesToProcess =
        _allMusicFiles.sublist(_currentOffset, end);

    final receivePort = ReceivePort();

    await Isolate.spawn(
        _processFilesInIsolate, [filesToProcess, receivePort.sendPort]);

    final albumMap = await receivePort.first as Map<String, List<MusicModel>>;

    _currentOffset += limit;

    final endTime = DateTime.now();
    print(
        'loadMoreMusicFiles took: ${endTime.difference(startTime).inMilliseconds} ms');

    return albumMap;
  }

  static Future<void> _processFilesInIsolate(List<dynamic> args) async {
    List<FileSystemEntity> files = args[0];
    SendPort sendPort = args[1];

    Map<String, List<MusicModel>> albumMap = {};

    List<Future<void>> futures = files.map((file) async {
      if (file is File) {
        try {

          final metadata = await MetadataRetriever.fromFile(file); // i think here is problem

          MusicModel music = MusicModel(
            id: file.path,
            title: metadata.trackName ?? file.path.split('/').last,
            artist: metadata.trackArtistNames != null &&
                    metadata.trackArtistNames!.isNotEmpty
                ? metadata.trackArtistNames![0]
                : 'Unknown Artist',
            album: metadata.albumName ?? 'Unknown Album',
            filePath: file.path,
            duration: metadata.trackDuration ?? 0,
            albumArt: metadata.albumArt,
            trackNumber: metadata.trackNumber ?? 1,
            genre: metadata.genre ?? 'Unknown Genre',
            releaseDate: metadata.year != null
                ? DateTime(metadata.year!)
                : DateTime(1970, 1, 1),
          );

          if (albumMap.containsKey(music.album)) {
            albumMap[music.album]!.add(music);
          } else {
            albumMap[music.album] = [music];
          }
        } catch (e) {
          print('Error processing file: ${file.path}, Error: $e');
        }
      }
    }).toList();

    await Future.wait(futures);
    sendPort.send(albumMap);
  }

thank you all.