I have a Xamarin application which plays remote(internet) audio files using the MediaPlayer with the following setup:
_mediaPlayer.SetDataSource(mediaUri);
_mediaPlayer.PrepareAsync();
Now I would like to change the implementation to also cache files. For the caching part I found a really nice library called MonkeyCache which saves the files in this JSON format:
{"$type":"System.Byte[], mscorlib","$value":"UklGRhAoAgBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YdAnAgAAAAAAAAAAAAAAAAAA+P/4/+z/7P8KAAoA7//v//L/8v8JAAkA6f/p//j/+P8FAAUA6P/o/wEAAQD+//7/5//n ................."}
So my MediaPlayer setup has now changed to:
if (Barrel.Current.Exists(mediaUri)){
var audio = Barrel.Current.Get<byte[]>(mediaUri);
_mediaPlayer.SetDataSource(???);
}else{
using (var webClient = new WebClient()){
var downloadDataBytes = webClient.DownloadData(mediaUri);
if (downloadDataBytes != null && downloadDataBytes.Length > 0)
{
Barrel.Current.Add(mediaUri, downloadDataBytes, TimeSpan.FromDays(1));
_mediaPlayer.SetDataSource(???);
}
}
}
I would like to play the audio from a byte[] instead of the mediaUri. Is there any way to actually play an in memory byte[]?
The only solutions that I could find were to create a FileInputStream out of a File by using a filepath, but the implementation of the MonkeyCache actually hashes the file name, before adding it:
static string Hash(string input){
var md5Hasher = MD5.Create();
var data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
return BitConverter.ToString(data);
}
Therefore the downloaded bytes, will be saved under:
/data/data/com.package.name.example/cache/com.package.name.example/MonkeyCacheFS/81-D6-E8-62-F3-4D-F1-64-A6-A1-53-46-34-1E-FE-D1
Even if I were to use the same hashing logic to actually compute the file path myself and use the FileInputStream which might be working by what I've read, it would defeat the purpose of using the var audio = Barrel.Current.Get<byte[]>(mediaUri);
functionality of the MonkeyCache.
However, if that is the only way, I will do it.
Edit: Even with my described approach, it would probably not work right away as even if I compute the right file name, it is still in JSON format.
Edit2: A working solution is:
var audio = Barrel.Current.Get<byte[]>(mediaUri);
var url = "data:audio/mp3;base64," + Convert.ToBase64String(audio);
_mediaPlayer.SetDataSource(url);