Can I use an imported file from FilePicker as a MediaPlayer source

0

I am working on an app that plays audio using the MediaPlayer. It works when the audio file to play is already in the Assets folder. However, my goal is to use the FilePicker plugin for the user to pick a file from their device to be played.

From the FilePicker, I am able to get a path (which seems to be a Uri), like content://com.android.providers.downloads.documents/document/6531. However, attempting use the MediaPlayer with this path (both as a string and as a Uri) results in Java.IO.IOException: 'setDataSource failed.: status=0x80000000'.

I'm assuming it's not possible to use the MediaPlayer on a file outside of the Assets folder. So my question becomes is there a way to add an asset to a project's asset folder when a path is provided? Or am I wrong, and is there a way to use the MediaPlayer given the Uri?

Here is the code of the button that handles importing:

Button browse = FindViewById<Button>(Resource.Id.browse);
browse.Click += async delegate
{
   var fileImp = await CrossFilePicker.Current.PickFile();
   if (fileImp != null)
   {
      path = fileImp.FilePath;
   }
};

And after sending the path to another class:

public void load()
{
   player = new MediaPlayer();

   player.SetDataSource(path);

   player.Prepare();
}

This other attempt at setting the data source does not work either, and gets the same error:

public void load()
{
   player = new MediaPlayer();

   Android.Net.Uri uri = Android.Net.Uri.Parse(songFileString);

   player.SetDataSource(Application.Context, uri);

   player.Prepare();
}

Any help is appreciated, thanks.

c#
android
xamarin
filepicker
asked on Stack Overflow May 20, 2020 by mayomatsuda

1 Answer

0

content://com.android.providers.downloads.documents/document/6531

You could try to convert the uri to the file path.

string filePath = null;
Android.Net.Uri uri = Android.Net.Uri.Parse(path);
if (DocumentsContract.IsDocumentUri(this, uri))
{
    string docId = DocumentsContract.GetDocumentId(uri);
    if (uri.Authority.Equals("com.android.providers.media.documents"))
    {
        string id = docId.Split(":")[1];
        string selection = MediaStore.Video.Media.InterfaceConsts.Id + "=" + id;
        filePath = getfilePath(MediaStore.Video.Media.ExternalContentUri, selection);
    }
    else if (uri.Authority.Equals("com.android.providers.downloads.documents"))
    {
        Android.Net.Uri contentUri = ContentUris.WithAppendedId(Android.Net.Uri.Parse("content://downloads/public_downloads"), long.Parse(docId));
        filePath = getfilePath(contentUri, null);
    }
}
else if (uri.Scheme.Equals("content", StringComparison.OrdinalIgnoreCase))
{
    filePath = getfilePath(uri, null);
}
else if (uri.Scheme.Equals("file", StringComparison.OrdinalIgnoreCase))
{
    filePath = uri.Path;
}

getfilePath method:

private string getfilePath(Android.Net.Uri uri, string selection)
{
  string path = null;
  var cursor = ContentResolver.Query(uri, null, selection, null, null);
  if (cursor != null)
  {
    if (cursor.MoveToFirst())
    {
        path = cursor.GetString(cursor.GetColumnIndex(MediaStore.Video.Media.InterfaceConsts.Data));
    }
    cursor.Close();
  }
  return path;
}
answered on Stack Overflow May 20, 2020 by Leo Zhu - MSFT

User contributions licensed under CC BY-SA 3.0