Android Question Failed to get the path of a video thumbnail using a MediaStore query with SDKVersion >= 30

GeoT

Active Member
Licensed User
Instead of creating a thumbnail of a video saved on my device, I am trying to obtain the path of that thumbnail already created by the system.
This path is saved in the MediaStore Collection.

First, I access the video table and get the ID of a video that I know is on my device by passing it its path.
(I use a query to the SQL library, ContentResolver and the android.provider.MediaStore.Video$Media class)

Then, I try to access the path of the corresponding thumbnail in the video thumbnail table, querying with the obtained Id and comparing it with the Ids saved in that table, in the VIDEO_ID field, and which links the two tables.
(I use a query to the SQL library, ContentResolver and the android.provider.MediaStore.Video.Thumbnails class)

But I only get that route when I use my smartphone with Android 6 (API 23). With my smartphone with Android 11 (API 30) my application does not crash but it does not perform the query.

I guess it has something to do with the new scoped storage starting with Android 11.

I have already stated that if the android SdkVersion < 30, the WRITE_EXTERNAL_STORAGE permission is required, and if it is 30 or greater, the MANAGE_EXTERNAL_STORAGE permission is required. And the way to give permissions with RuntimePermissions and with an intent, respectively.

I also put

B4X:
SetApplicationAttribute(android:requestLegacyExternalStorage, true)

But I still can't get that route with Android 11.

Any ideas?
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
Of course. I gave it a chance. :)
And it showed me the same as it showed you.
before i get to #20, let me ask you about #19: the theme of this thread involves loading video thumbnails. i posted something that enables you to do that. what was the goal of changing something that works for something that doesn't?
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
Java:
static Bitmap getThumbnail(ContentResolver cr, long videoId, int kind, BitmapFactory.Options options)
Return thumbnail representing a specific video item. If a thumbnail doesn't exist, this method will block until it's generated. Callers are responsible for their own in-memory caching of returned values.
It seems to create the thumbnail if it doesn't exist.
But it's not what I'm looking for.

And this method was deprecated in API level 29.
Callers should migrate to using ContentResolver#loadThumbnail, since it offers richer control over requested thumbnail sizes and cancellation behavior.
:rolleyes:
you wanted thumbnails. what does it matter when the os creates them? in my experience, thumbnails are created when an image or video is added to the database. (after creating my test videos for you but before running the example, i checked for thumbnails with a file explorer. the thumbnails' creation times were the same as those of the videos.)
if something does not exist but could exist if you waited less than a second for the os to create it, why wouldn't you wait? what sense does it make to tell a user there is no thumbnail when you provide the requested thumbnail if generated on demand? besides, i put the job in a service (specifically not to tie up the ui). in any case, it could easily be changed to run in an asynctask or thread.

as to the getThumbnail()'s being deprecated, you can simply swap it out:

// Bitmap bm = MediaStore.Video.Thumbnails.getThumbnail(resolver, imageId, MediaStore.Video.Thumbnails.MICRO_KIND,null);
Size size = new Size(300,300);
CancellationSignal signal = new CancellationSignal();
Bitmap bm = resolver.loadThumbnail (imageUri, size, signal);

it runs the same. i used getThumbnails() to show you how to get thumbnails by letting the system do it instead of trying to access them directly.
i don't know what to make of your mods to the example; as far as i can see, you took something that worked and made it not work...
 
Upvote 0

GeoT

Active Member
Licensed User
Yes, drgottjr.
Now I saw it. I hadn't noticed until you doubted it.
You're right about everything.

My only intention was to see if this modification could be made to save processing time, if it could be done and if it was worth it.
Now I see that it doesn't.

Thank you.
 
Last edited:
Upvote 0

GeoT

Active Member
Licensed User
Hi, drgottjr.
By putting pieces together I have managed to obtain bitmaps of video thumbnails, just as you showed me that you did with Java code, but with B4A code.

So:

B4X:
Sub GetBitmapsOfVideoThumbnails

    Dim MediaStore As JavaObject
    Dim uri As Object
    Dim MediaStore_Video_Thumbnails As JavaObject
    
    MediaStore.InitializeStatic("android.provider.MediaStore.Video$Media")
    uri = MediaStore.GetField("EXTERNAL_CONTENT_URI")        'content://media/external/video/media fo videos

    MediaStore_Video_Thumbnails.InitializeStatic("android.provider.MediaStore.Video.Thumbnails")


    Dim cr As ContentResolver        'ContentResolver library
    cr.Initialize("cr")
    
    Dim thumbCursor As Cursor    'SQL lib
    thumbCursor = cr.Query(uri, Null, "mime_type LIKE 'video/%'", Null, Null)            'LIMIT not work on android 11+
    
    Log("thumbCursor.RowCount = " & thumbCursor.RowCount)
    
    If thumbCursor <> Null And thumbCursor.RowCount > 0 Then

        For i = 0 To thumbCursor.RowCount - 1
            thumbCursor.Position = i
            
            Private imageId As Long = thumbCursor.GetString("_id")
            Log(imageId)
'            Log(uri & "/" & imageId)
            Log(thumbCursor.GetString("_data"))


            Dim r As Reflector
            Dim cres As Object
            r.Target = r.GetContext
            cres = r.RunMethod("getContentResolver")
            
            Try
                Private bm As Bitmap = MediaStore_Video_Thumbnails.RunMethod("getThumbnail", Array As Object(cres, imageId, 3, Null))    '3 = MICRO_KIND
                Log(bm.Width & " x " & bm.Height)
            Catch
                Log(LastException)
            End Try
        Next
    End If
End Sub

Sub btnSearch_Click   
    GetBitmapsOfVideoThumbnails
End Sub

(I don't show the permissions code)
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i assumed you would see what you needed to do and then do it in b4a/javaobject, given your original project.:)
 
Upvote 0

GeoT

Active Member
Licensed User
And to do it with ContentResolver.loadThumbnail(...) you have to write:

B4X:
Dim SizeObj As JavaObject
Dim size As JavaObject = SizeObj.InitializeNewInstance("android.util.Size", Array As Object(96, 96))
Log(size)

Dim uri2 As JavaObject
Dim u As JavaObject = uri2.InitializeStatic("android.net.Uri").RunMethod("parse", Array As String(uri & "/" & imageId))
LogColor(u, Colors.Magenta)
            
Dim csign As JavaObject
Dim cs As JavaObject = csign.InitializeNewInstance("android.os.CancellationSignal", Null)
Log(cs)

Dim ctxt As JavaObject
Dim ContentResolver As JavaObject = ctxt.InitializeContext.RunMethodJO("getContentResolver", Null)

Dim Thumbnail As Bitmap
Thumbnail = ContentResolver.RunMethod("loadThumbnail", Array(u, size, csign))
Log(Thumbnail.Width & " xx " & Thumbnail.Height)

;)
 
Last edited:
Upvote 0
Top