Last active
September 28, 2020 23:16
-
-
Save AmSmart/8371b15ba089b44e19aede3e78bb8569 to your computer and use it in GitHub Desktop.
Xamarin.Android dependency service to extract a thumbnail from a video
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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