Xamarin.Android dependency service to extract a thumbnail from a video
using Xamarin.Forms; | |
namespace YourApp.Shared.DependencyServices | |
{ | |
public interface IThumbnailGenerator | |
{ | |
ImageSource GenerateThumbnailImageSource(string url, long usecond); | |
string GenerateThumbnailAsPath(string url, long usecond, string appCachePath); | |
} | |
} | |
// This is a simple interface in the shared Xamarin.Forms project. |
using Android.Graphics; | |
using Android.Media; | |
using StatusSaver.DependencyServices; | |
using StatusSaver.Droid.DependencyServices; | |
using System.IO; | |
using Xamarin.Forms; | |
[assembly: Dependency(typeof(ThumbnailGeneratorAndroid))] | |
namespace YourApp.Android.DependencyServices | |
{ | |
public class ThumbnailGeneratorAndroid : IThumbnailGenerator | |
{ | |
public ImageSource GenerateThumbnailImageSource(string url, long usecond) | |
{ | |
// Extract thumbnail from video into a bitmap | |
MediaMetadataRetriever retriever = new MediaMetadataRetriever(); | |
retriever.SetDataSource(url); | |
Bitmap bitmap = retriever.GetFrameAtTime(usecond); | |
//Convert bitmap to a 'Stream' and then to an 'ImageSource' | |
if (bitmap != null) | |
{ | |
MemoryStream stream = new MemoryStream(); | |
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream); | |
byte[] bitmapData = stream.ToArray(); | |
return ImageSource.FromStream(() => new MemoryStream(bitmapData)); | |
} | |
return null; | |
} | |
public string GenerateThumbnailAsPath(string url, long usecond, string appCachePath) | |
{ | |
MediaMetadataRetriever retriever = new MediaMetadataRetriever(); | |
retriever.SetDataSource(url); | |
Bitmap bitmap = retriever.GetFrameAtTime(usecond); | |
//Convert bitmap to a 'Stream', save to a cache folder and then return it's output path | |
if (bitmap != null) | |
{ | |
int slashLastIndex = url.LastIndexOf('/'); | |
int dotLastIndex = url.LastIndexOf('.'); | |
int fileNameLength = url.Length - (url.Length - dotLastIndex) - slashLastIndex - 1; | |
string fileName = url.Substring(slashLastIndex + 1, fileNameLength); | |
string outputPath = System.IO.Path.Combine(appCachePath, fileName + ".png"); | |
FileStream stream = new FileStream(outputPath, FileMode.CreateNew); | |
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream); | |
stream.Flush(); | |
stream.Close(); | |
return outputPath; | |
} | |
return null; | |
} | |
} | |
} | |
/* | |
This is the implementation of the interface below in the Android project. | |
Both methods above essentially do the same thing in different ways. | |
You can use the first method by binding your ImageView's source to the ImageSource object returned. | |
You can use the second method by setting your ImageView's source to the path it returns | |
You can also ignore all the processing I did after coverting the bitmap into a stream and return the | |
Stream object directly if it fits your scenario | |
I found out that using the second method(caching the bitmap and returning a path to it) was more performant in my case, | |
this was probably because I was dealing with a lot of images being loaded into a CollectionView. Use any one that suits you. Remember | |
to clean up your cache folder just in case you use this😉 | |
Do whatever works for you. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment