Android Question MediaMetadataRetriever setDataSource with URI

RandomCoder

Well-Known Member
Licensed User
Longtime User
I really need some help as it's clear I have no idea what I'm doing :(
Originally posted here but got no response, possibly because the thread is marked as solved and that's why I've started a new thread.

Basically I'm trying to center my Videoview based on the size of the video about to be played. The problem I have is that the file is not stored locally, its on my home server and so I need to pass a URI to the setDataSource method of the MediaMetadataRetriever class.

This code using the reflection library...
B4X:
    Dim rfl As Reflector
    Dim obj As Object
    Dim context As JavaObject
    Dim b As Bitmap
   
    context = context.InitializeStatic("anywheresoftware.b4a.BA").GetField("applicationContext")
    obj = rfl.CreateObject("android.media.MediaMetadataRetriever")
    rfl.Target = obj
    rfl.RunMethod3("setDataSource", context, "java.lang.Object", vvPath, "java.lang.String")
    b = rfl.RunMethod3("getFrameAtTime", 0, "java.lang.long", 3, "java.lang.int")

    Log("HEIGHT=" & b.Height)
    Log("WIDTH=" & b.Width)
Produces the following error...
java.lang.NoSuchMethodException: setDataSource [class java.lang.Object, class java.lang.String]

And this code using a Java Object...
B4X:
Dim context As JavaObject
Dim vvFileURI As Uri
Dim mediaScanner As JavaObject
Dim b As Bitmap
    context = context.InitializeStatic("anywheresoftware.b4a.BA").GetField("applicationContext")
    vvFileURI.Parse(vvPath)
    mediaScanner.InitializeStatic("android.media.MediaMetadataRetriever")
    mediaScanner.RunMethod("setDataSource", Array As Object(context, vvFileURI))
    b = mediaScanner.RunMethod("getFrameAtTime", Array As Object(0, 3))
    Log("HEIGHT=" & b.Height)
    Log("WIDTH=" & b.Width)
Produces the following error (which I think is a step nearer :D)
java.lang.IllegalArgumentException: expected receiver of type android.media.MediaMetadataRetriever, but got java.lang.Class<android.media.MediaMetadataRetriever>

I really don't understand as that last error message states that it expected android.media.MediaMetadataRetriever but got exactly that. I know its case sensitive but what it expected and what it got are identical. What am I doing wrong?

This is the documentation for the method I am attempting to call...
public void setDataSource (Context context, Uri uri) Added in API level 10

Sets the data source as a content Uri. Call this method before the rest of the methods in this class. This method may be time-consuming.

Parameters
context the Context to use when resolving the Uri
uri the Content URI of the data you want to play
Throws
IllegalArgumentException if the Uri is invalid
SecurityException if the Uri cannot be used due to lack of permission.

I'm at a loss what to try next and have read through the forum and other sources but the only thing I've managed to achieve is a variety of different error messages.

The path to my file is "http://192.168.0.100:49152/content/media/object_id/30342/res_id/0/ext/file.avi" I'm guessing that it's not as simple as passing this as a string which is why in the last example I've attempted to parse it into a URI.

I've waffled enough, hopefully someone can understand what I need and offer some advice?

Thanks,
RandomCoder
 

RandomCoder

Well-Known Member
Licensed User
Longtime User
Another evening wasted, not getting anywhere with this but I've found a possible solution on the web...
== SOLUTION ==

I started looking into william-seemann's answer and it led me to this:MediaMetadataRetriever.setDataSource(String path) no longer accepts URLs

Comment #2 on this post mentions using a different version of setDataSource() that still accepts remote URLs.

Here's what I ended up doing and it's working great:
B4X:
private Bitmap downloadBitmap(final String url) {
     final MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
     metaRetriever.setDataSource(url, new HashMap<String, String>());
     try {
        final byte[] art = metaRetriever.getEmbeddedPicture();
        return BitmapFactory.decodeByteArray(art, 0, art.length);
     } catch (Exception e) {
        Logger.e(LOGTAG, "Couldn't create album art: " + e.getMessage());
        return BitmapFactory.decodeResource(getResources(), R.drawable.album_art_missing);
     }
  }

It's using the following method...
public void setDataSource (String uri, Map<String, String> headers) Added in API level 14
Sets the data source (URI) to use. Call this method before the rest of the methods in this class. This method may be time-consuming.

Parameters
uri The URI of the input media.
headers the headers to be sent together with the request for the data
Throws
IllegalArgumentException If the URI is invalid.

Only problem is that I don't know what headers to send? o_O
I've tried creating a map and putting the following into it...
hashMap.Put("", "")
hashMap.Put("Authorization", "TOKEN")
hashMap.Put("rtsp_transport", "http")
hashMap.Put("transferMode.dlna.org", "Streaming")
But everything I try just returns Method: setDataSource not matched.

It looks like I'll have to try another approach. I'm thinking that I should be able to get the info from the UPNP server along with the other info I'm already getting. Maybe this is a better approach anyhow?

If you have any idea where I am going wrong be sure to let me know, I don't like to be beaten :mad:

Thanks,
RandomCoder
 
Upvote 0
Top