XamarinMediaManager
XamarinMediaManager copied to clipboard
Album and Display Image doesn't change
🐛 Bug Report
I am using this package and it is quite well. However, when i want to change the media item display, album and image it doesn't update or change the images. Here is the code.
// fileUri = https://www.azee.tech/Dari/001.mp3
var item = (MediaItem)await CrossMediaManager.Current.Extractor.CreateMediaItem(fileUri);
var reciterImageUri = "https://www.azee.tech/sudais.jpg"; // this is the image uri
var image = new Image() { Source = ImageSource.FromUri(new Uri(reciterImageUri)) };
if (item != null)
{
item.Id = string.Format("{0},{1},{2},{3},{4},{5},{6}", (short)mode, chapterId, reciter.ReciterID, playlistId, playlistChapterId, -1, -1);
item.IsMetadataExtracted = false;
item.Title = string.Format("{0} - {1} ({2})", c.ChapterID, c.ArabicEnglishName, c.EnglishName);
item.Album = reciter.Name;
item.Artist = reciter.Name;
//none of these work
item.AlbumImage = image;
item.AlbumImageUri = reciterImageUri;
item.DisplayImage = image;
item.DisplayImageUri = reciterImageUri;
item.Image = image;
item.ImageUri = reciterImageUri;
}
return item;
Expected: Should the change the album and display image.
Actual: Doesn't change Album or Display image
The media file play works as expected, but the image doesn't change.
I understand this was reported in #709, but closed without working solution.
Hi @arahmancsd Do you found a solution? I encounter the same issue both on iOS and Android regarding the Album / Display image.
This seems to be still a bug in the package, I have tried different methods but none worked.
Encountering the same issue.
I've finally found a way to display an Album Image like this:
CrossMediaManager.Current.Queue.Current.IsMetadataExtracted = false;
var webUrlImage = "https://my.url.com/mycover.jpg";
CrossMediaManager.Current.Queue.Current.DisplayImageUri = webUrlImage;
CrossMediaManager.Current.Queue.Current.AlbumImageUri = webUrlImage;
CrossMediaManager.Current.Queue.Current.ImageUri = webUrlImage;
CrossMediaManager.Current.Notification.UpdateNotification();
CrossMediaManager.Current.Extractor.UpdateMediaItem(CrossMediaManager.Current.Queue.Current);
But I always display the same Image, as I play audio stream of a Web Radio: I display the cover of this radio.
I have used your code in PropertyChanged, MetadataUpdated, OnStateChanged (only in playing), and also added your code right after await play(), but none worked for me. Is it working in emulator for you?
@Goldstrike just tried this code snippet. Works on Android but not on iOS for me. Have you tested this on iOS?
UPDATE:
A full rebuild of iOS has actually fixed this! So yes, this code does indeed work.
Actually managed to work in iOS. The image path must be https and JPG/JPEG only. However, the same code doesn't work with Android.
@arahmancsd I didn't have any problem on Android to display the image.
Finally, I solved this mystery (at least for me) in Android and iOS. I'll go ahead and get straight to the code.
Part 1
It would be faster to create a MediaItem
object when you have the raw data rather than using Extracter
, but in both cases, it would work. Extractor is slower compared to raw data to create a MediaItem
object. So in my case I had the raw data so I created a MediaItem
object
var mediaItem = new MediaItem()
{
MediaUri = mediaUri,
IsMetadataExtracted = false,
Id = something,
Title = title,
DisplayTitle = displayTitle,
DisplaySubtitle = displaySubtitle,
DisplayImageUri = imageUri, // valid https jpg URL => setting this works with iOS out of the box
AlbumImageUri = imageUri, // valid https jpg URL => setting this works with iOS out of the box
ImageUri = imageUri, ///valid https jpg URL => setting this works with iOS out of the box
Album = albumName,
Author = author,
Artist = artist,
Genre = genre,
DisplayImage = null, // this is optional => setting this in iOS somehow creates a problem so you can remove it
DownloadStatus = ...,
MediaLocation = ...,
};
However, you can create your mediaitem object with Extractor as well.
Part 2
In StateChanged
add the following (since I care about Playing only so it is up to you)
if (CrossMediaManager.Current.State == MediaPlayerState.Playing
&& CrossMediaManager.Current.Queue.Current is IMediaItem mediaItem
&& mediaItem is not null)
{
mediaItem = await mediaItem.AddDisplayImageAsync(mediaItem.DisplayImageUri);
CrossMediaManager.Current.Notification.UpdateNotification();
await CrossMediaManager.Current.Extractor.UpdateMediaItem(mediaItem);
}
Part 3 // This is an extension
using MediaManager.Library;
#if ANDROID
using Android.Graphics;
using Android.OS;
using Android.Support.V4.Media;
#endif
#if IOS
using Foundation;
using UIKit;
#endif
// Although this is not required in iOS, but I am having a function to care of it.
public static async Task<IMediaItem> AddDisplayImageAsync(this IMediaItem mediaItem, string imageUrl)
{
if (mediaItem is not null && !string.IsNullOrWhiteSpace(imageUrl))
{
try
{
using HttpClient client = new();
var stream = await client.GetStreamAsync(imageUrl).ConfigureAwait(false);
#if ANDROID
var bitmap = BitmapFactory.DecodeStream(stream);
mediaItem.DisplayImage = bitmap;
#elif IOS
using var imageData = NSData.FromStream(stream);
using var image = UIImage.LoadFromData(imageData);
#endif
}
catch (Exception ex)
{
mediaItem.DisplayImage = null;
}
}
return mediaItem;
}
Additionally, if you are using Extractor you won't have to add StateChanged. You can add a display image directly by returning an object from AddDisplayImageAsync without the extension (something like below). However, please note that this would be slower for the list/playlist. So for performance, it is good to place it in StateChanged
.
private async Task<object> GetDisplayImageAsync(string imageUrl)
{
if (!string.IsNullOrWhiteSpace(imageUrl))
{
try
{
using HttpClient client = new();
var stream = await client.GetStreamAsync(imageUrl).ConfigureAwait(false);
#if ANDROID
return BitmapFactory.DecodeStream(stream);
#elif IOS
using var imageData = NSData.FromStream(stream);
return UIImage.LoadFromData(imageData);
#endif
}
catch (Exception)
{
}
}
return null;
}