audio_service icon indicating copy to clipboard operation
audio_service copied to clipboard

How to load a local image into a curtain using: - AudioServiceBackground.setMediaItem ( and property: - artUri

Open Okladnoj opened this issue 4 years ago • 11 comments

Is your feature request related to a problem? Please describe. How to load a local image into a curtain using: "artUri"

mistakenly I asked the question elsewhere: https://github.com/ryanheise/audio_service/issues/354#issuecomment-726042710 please look.

My code

         MediaItem(
           id: _params['id']?.toString() ?? AudioService.MEDIA_ROOT_ID,
           album: _mediaDataItuns.collectionName,
           title: _params['name'],
           artist: _mediaDataItuns.artistName,
           displayTitle: _params['name'],
           displaySubtitle: _mediaDataItuns.displaySubtitle,
           artUri: _artUri,
           extras: {
             'id': _params['id'],
             'url': _params['url'],
             'name': _params['name'],
             'trackName': _mediaDataItuns.trackName,
             'artworkUrl30': _mediaDataItuns.artworkUrl30,
             'artworkUrl100': _mediaDataItuns.artworkUrl100,
             'artworkUrl820': _mediaDataItuns.artworkUrl820,
             'control': event?.info?.title,
           },
         ),

Describe the solution you'd like I think you need to introduce several ways to load artUri

  • artUrl
  • artAsset
  • artByte

Describe alternatives you've considered Here's what I've tried: but it did not help(((

/// got full path
var tempDir = await path_provider.getApplicationDocumentsDirectory();

//AND
var _artUri = join("file://", tempDir.uri.path, _params['artUri']);

/// OR
var _artUri = join(tempDir.uri.path, _params['artUri']);

Additional context

Okladnoj avatar Nov 12 '20 13:11 Okladnoj

These are good suggestions. I hadn't yet thought about the bytes option, but I do have plans to add an assets option.

While the bytes option seems like a good idea, it will probably be too inefficient to transfer bytes over the platform channel as another MediaItem field because these media items get transferred frequently. I think the assets option will probably be enough.

Your workaround will not work because Flutter assets are not stored in the documents directory. They are embedded as bytes within the app binary itself. You read assets in your program as a stream of bytes via rootBundle.

Until this feature is implemented in the plugin, you can still workaround it. What you need to do is read the asset out of rootBundle and copy it into a file on app initialisation, then you can pass the file:// URI pointing to that in your artUri.

ryanheise avatar Nov 12 '20 13:11 ryanheise

image what's wrong with my path?

image my pubspec.yaml

image and import.

what have I missed?

Okladnoj avatar Nov 12 '20 14:11 Okladnoj

You missed this:

Your workaround will not work because Flutter assets are not stored in the documents directory. They are embedded as bytes within the app binary itself. You read assets in your program as a stream of bytes via rootBundle.

You are using rootBundle.loadString but your asset is an image in a binary format, not a string. You need to read the bytes and store those bytes into a file. These are not my APIs, so I can't provide more advice on that. But you can take a look at how I implemented asset loading in just_audio for inspiration.

ryanheise avatar Nov 12 '20 15:11 ryanheise

Thank you for the clarification. You have complete information in the first message !!!

I read your previous message for the second time and now I found the right solution !!!)))


        Directory appDir = await path_provider.getApplicationDocumentsDirectory();
        ByteData bytes = await rootBundle.load(_params['artUri']);
        File _file = File(join(appDir.path, 'default_images.webp'));
        File _newFile = await _file.writeAsBytes(bytes.buffer.asUint8List());
        String _artUri = "file://" + _newFile.path;

        AudioServiceBackground.setMediaItem(
          MediaItem(
            id: _params['id']?.toString() ?? AudioService.MEDIA_ROOT_ID,
            album: _mediaDataItuns.collectionName,
            title: _params['name'],
            artist: _mediaDataItuns.artistName,
            displayTitle: _params['name'],
            displaySubtitle: _mediaDataItuns.displaySubtitle,
            artUri: _artUri,
            extras: {
              'id': _params['id'],
              'url': _params['url'],
              'name': _params['name'],
              'trackName': _mediaDataItuns.trackName,
              'artworkUrl30': _mediaDataItuns.artworkUrl30,
              'artworkUrl100': _mediaDataItuns.artworkUrl100,
              'artworkUrl820': _mediaDataItuns.artworkUrl820,
              'control': event?.info?.title,
            },
          ),
        );

But I still continue to wait for your decision in new version:

  • artAsset

Okladnoj avatar Nov 12 '20 16:11 Okladnoj

I'm glad you figured it out. I will still leave your feature request open until I implement the feature.

ryanheise avatar Nov 13 '20 01:11 ryanheise

ryanheise says "These are good suggestions. I hadn't yet thought about the bytes option, but I do have plans to add an assets option." Do you have implemented asset image option?

csacchetti avatar May 16 '22 09:05 csacchetti

I haven't. If I do implement it, it will be announced in the CHANGELOG.

ryanheise avatar May 16 '22 12:05 ryanheise

Do you have any advice at this point? My app works offline so I can't get the image from the internet. Is there any way to load in the artUri parameter of the MediaItem a local image? Thanks

csacchetti avatar May 18 '22 10:05 csacchetti

I did give advice above in my very first reply. Maybe you can read it and ask me specifically about what I have written in that above advice.

ryanheise avatar May 18 '22 10:05 ryanheise

👍🏻 Thanks

csacchetti avatar May 19 '22 14:05 csacchetti

For people still needing to load local images as art URI here is an updated example:

import 'package:path_provider/path_provider.dart';

final Directory appDir = await getApplicationDocumentsDirectory();
File file = File('${appDir.path}/cover.jpg');

//coverImageBytes of type Uint8List
File newFile = await file.writeAsBytes(coverImageBytes);
String artUri = "file://${newFile.path}";

return MediaItem(id: id, album: book.title, artist: chapter.title, title: book.title, artUri: Uri.tryParse(artUri));