B4A Library [Lib] MediaBrowser

Hello,

This library lists the media content (audio, image and video) of the MediaStore (a database containing meta data for all available media on both internal and external storage devices). It includes an audio player and a media scanner (to scan the new media and add them to the MediaStore).

I added new functions to the library esAudioMediaBrowser provided by Lagore, improved a bit the existing ones, and extended the stuff to images and videos.
The demo (a media gallery) needs the libs Reflection & StringUtils. It displays only files stored on your external SD card (but the lib can handle internal files).

This lib does not work with Android versions < Gingerbread (2.3).

List of properties and methods:
  • GetAudioFieldByID (External As Boolean, ID As Long, Field As String) As String
    Returns a field from the MediaStore about the specified audio file.
    Examples of field: FIELD_COMPOSER, FIELD_DATE_MODIFIED, FIELD_MIME_TYPE, FIELD_SIZE...
  • GetAudioFileInfo (Path As String, File As String) As Map
    Returns a Map containing info from the MediaStore about an audio file.
    The fields that are returned are:
    "ID"
    "Title"
    "Album"
    "Artist"
    "Track"
    "Year"
    "Location"
    "DisplayName"
    "Duration" (in ms)
  • GetAudioFileInfoByID (External As Boolean, ID As Long) As Map
    Returns a Map containing info from the MediaStore about an audio file.
    The fields that are returned are:
    "ID"
    "Title"
    "Album"
    "Artist"
    "Track"
    "Year"
    "Location"
    "DisplayName"
    "Duration" (in ms)
  • GetExifAttribute (Location As String, Attribute As String) As String
    Returns the requested attribute from the Exif data of the specified image.
    Location = complete path name for the file.
    The complete list of attributes can be found here: https://developer.android.com/reference/android/media/ExifInterface
  • GetExifLatLong (Location As String, LatLong As Float()) As Boolean
    Stores the latitude and longitude value of the specified image in a float array. Returns False if these Exif data are not available.
    Location = complete path name for the file.
  • GetExtImageFileInfo (Location As String) As Map
    Returns a Map containing info from the MediaStore about an external image file.
    Location = complete path name for the file.
    The fields that are returned are:
    "ID"
    "Location"
    "DisplayName"
    "DateTaken" (in ticks from 1970)
    "Height" (with Android 3.0+)
    "Width" (with Android 3.0+)
    "Size" (in bytes)
  • GetExtVideoFileInfo (Location As String) As Map
    Returns a Map containing info from the MediaStore about an external video file.
    Location = complete path name for the file.
    The fields that are returned are:
    "ID"
    "Location"
    "DisplayName"
    "DateTaken" (in ticks from 1970)
    "Resolution" (can be Null for some files)
    "Size" (in bytes)
  • GetImageDimensions (Location As String) As Map
    Returns a map containing width and height of the specified file.
    Location = complete path name for the file.
  • GetImageFieldByID (External As Boolean, ID As Long, Field As String) As String
    Returns a field from the MediaStore about the specified image file.
    Examples of field: FIELD_DATE_MODIFIED, FIELD_MIME_TYPE, FIELD_ORIENTATION...
  • GetImageFileInfoByID (External As Boolean, ID As Long) As Map
    Returns a Map containing info from the MediaStore about an image file.
    The fields that are returned are:
    "ID"
    "Location"
    "DisplayName"
    "DateTaken" (in ticks from 1970)
    "Height" (with Android 3.0+)
    "Width" (with Android 3.0+)
    "Size" (in bytes)
  • GetImgThumbnailByID (ID As Long, Mini As Boolean) As android.graphics.Bitmap
    Returns the micro thumbnail (96x96) or mini thumbnail (512x384) of an image file (it is generated if it doesn't exist).
  • GetMediaAudioList (External As Boolean, SortCol As String) As Map
    Returns a Map containing a list of all Audio files in the MediaStore which can be sorted.
    The allowed fields for sorting are:
    Null (= FIELD_ID)
    FIELD_ALBUM
    FIELD_ARTIST
    FIELD_COMPOSER
    FIELD_DATA (location)
    FIELD_DATE_ADDED
    FIELD_DATE_MODIFIED
    FIELD_DISPLAY_NAME
    FIELD_DURATION
    FIELD_MIME_TYPE
    FIELD_SIZE
    FIELD_TITLE
    FIELD_TRACK
    FIELD_YEAR
    The fields that are returned are:
    "ID"
    "Title"
    "Album"
    "Artist"
    "Track"
    "Year"
    "Location"
    "DisplayName"
    "Duration" (in ms)
  • GetMediaImageList (External As Boolean, SortCol As String) As Map
    Returns a Map containing a list of all Image files in the MediaStore which can be sorted.
    The allowed fields for sorting are:
    Null (= FIELD_ID)
    FIELD_DATA (location)
    FIELD_DATE_ADDED
    FIELD_DATE_MODIFIED
    FIELD_DATE_TAKEN
    FIELD_DISPLAY_NAME
    FIELD_HEIGHT
    FIELD_MIME_TYPE
    FIELD_ORIENTATION
    FIELD_SIZE
    FIELD_TITLE
    FIELD_WIDTH
    The fields that are returned are:
    "ID"
    "Location"
    "DisplayName"
    "DateTaken" (in ticks from 1970)
    "Height" (with Android 3.0+)
    "Width" (with Android 3.0+)
    "Size" (in bytes)
  • GetMediaVideoList (External As Boolean, SortCol As String) As Map
    Returns a Map containing a list of all Video files in the MediaStore which can be sorted.
    The allowed fields for sorting are:
    Null (= FIELD_ID)
    FIELD_DATA (location)
    FIELD_DATE_ADDED
    FIELD_DATE_MODIFIED
    FIELD_DATE_TAKEN
    FIELD_DISPLAY_NAME
    FIELD_MIME_TYPE
    FIELD_RESOLUTION
    FIELD_SIZE
    FIELD_TITLE
    The fields that are returned are:
    "ID"
    "Location"
    "DisplayName"
    "DateTaken" (in ticks from 1970)
    "Resolution" (can be Null for some files)
    "Size" (in bytes)
  • GetVideoFieldByID (External As Boolean, ID As Long, Field As String) As String
    Returns a field from the MediaStore about the specified video file.
    Examples of field: FIELD_DATE_ADDED, FIELD_DATE_MODIFIED, FIELD_MIME_TYPE...
  • GetVideoFileInfoByID (External As Boolean, ID As Long) As Map
    Returns a Map containing info from the MediaStore about a video file.
    The fields that are returned are:
    "ID"
    "Location"
    "DisplayName"
    "DateTaken" (in ticks from 1970)
    "Resolution" (can be Null for some files)
    "Size" (in bytes)
  • GetVideoThumbnailByID (ID As Long, Mini As Boolean) As android.graphics.Bitmap
    Returns the micro thumbnail (96x96) or mini thumbnail (512x384) of a video file (it is generated if it doesn't exist).
    There's a known bug on some Android versions with micro thumbnails:
    If the micro thumbnail can't be generated (e.g. video file format not recognized), the result is either null or a random thumbnail. Thus, for video files, it is strongly recommended to check if the mini thumbnail is initialized before trying to get the micro thumbnail.
  • Initialize (EventName As String)
  • MediaAudioPlay (External As Boolean, ID As Int)
    Plays an audio file.
    Raises the "MediaCompleted" event when the file end is reached.
  • MediaIsLooping As Boolean
    Checks whether the player is looping or non-looping.
  • MediaIsPlaying As Boolean
  • MediaLength As Int
    Returns the duration in ms.
  • MediaPause
  • MediaPosition As Int
    Gets the current playback position.
  • MediaResume
  • MediaSeek (position As Int)
    Seeks to specified time position (in ms).
    Raises the event "SeekCompleted" when the position change has been completed.
  • MediaSetLooping (Looping As Boolean)
    Sets the player to be looping or non-looping.
  • MediaSetVolume (leftVolume As Float, rightVolume As Float)
    Sets the volume on this player (and this player only).
    Note that the passed volume values are raw scalars. UI controls should be scaled logarithmically.
    This function must be called AFTER MediaAudioPlay.
  • MediaStop
    Stops the playback and releases the allocated resources.
  • ScanNewMedia (Paths As String())
    Requests the media scanner to scan the given files and add them to the MediaStore.
    Raises the "ScanCompleted" event after each file is scanned.
Warning:
There's a known bug on some Android versions with micro thumbnails:
If the micro thumbnail can't be generated (e.g. video file format not recognized), the result is either null or a random thumbnail. Thus, for video files, it is strongly recommended to check if the mini thumbnail is initialized before trying to get the micro thumbnail.


v1.2:
I fixed two bugs.

v1.21:
I removed the excessive log entries.
I removed all the Try/Catch that silently trapped errors.

v1.3:
This version requires Java 7 and B4A v3.82+.
I added 3 functions:
- GetImageFileInfoByID(External As Boolean, ID As Long) As Map;
- GetVideoFileInfoByID(External As Boolean, ID As Long) As Map;
- ScanNewMedia(Paths() As String).
I updated the demo so it works with recent Android versions.

v1.31:
I fixed a mistake in two functions introduced in v1.3.

v1.4:
I fixed an issue with API 30;
I added five functions: GetAudioFieldByID, GetImageFieldByID, GetVideoFieldByID, GetExifAttribute and GetExifLatLong;
I added a few FIELD constants;
I updated the demo to display the following fields: composer, orientation, latitude and longitude.

Enjoy,
Fred
 

Attachments

  • MediaBrowser v1.4.zip
    80.7 KB · Views: 1,047
Last edited:

Informatix

Expert
Licensed User
Longtime User
hello mr informatix , glad to use ur great library , its really fast , i have some suggestion if u have time for updates :
it seems ur using the native mediaplayer class , i've done my own wrapper for this class and it succeeded to load the cover bitmap of the mp3 file by using :
B4X:
@ShortName("MetaData")
public static class MetaD {
     MediaMetadataRetriever Meta = new MediaMetadataRetriever();
         public void LoadFile(String file){
            Meta.setDataSource(file);
           }
public byte[] Picture(){
             return Meta.getEmbeddedPicture();
         }
but my wrapper is pretty slow while retreiving informations i dont know why.
i suggest u to include this line cz i need to display covers in the list.
The minimal API version for my library is 7. The minimal API version for your change is 10, so I cannot include it. But thanks for the suggestion. If I decide to drop old versions, I will probably add it.

i also suggest to make a sub for path , to make an option wish folder to search ,and thank u so mush for ur efforts .

I'm not sure to understand your request.
 

Mrjoey

Active Member
Licensed User
Longtime User
The minimal API version for my library is 7. The minimal API version for your change is 10, so I cannot include it. But thanks for the suggestion. If I decide to drop old versions, I will probably add it.


I'm not sure to understand your request.
well when i intialize MB it will gives a map of all media files in the media folders like music , whatsup , and notifications : so i would like to control MB and tell it to search in a specific folder not all folders , because i would like to include a tab in the list containing folders and then click on each folder and display a list of all content in that folder , is that possible? thank u
API 7 doesnt include this function?
B4X:
public byte[] Picture(){
            return Meta.getEmbeddedPicture();
        }
 

Informatix

Expert
Licensed User
Longtime User
well when i intialize MB it will gives a map of all media files in the media folders like music , whatsup , and notifications : so i would like to control MB and tell it to search in a specific folder not all folders , because i would like to include a tab in the list containing folders and then click on each folder and display a list of all content in that folder , is that possible? thank u
The library queries a database; it does not search itself on the storage media, so the speed improvement by restricting the folder in the query is neglectable. My suggestion: get the map with all files, then filter the result folder by folder (if m.Location = "myfolder" etc.).

API 7 doesnt include this function?
B4X:
public byte[] Picture(){
            return Meta.getEmbeddedPicture();
        }
getEmbeddedPicture is in API 10.
 

Mrjoey

Active Member
Licensed User
Longtime User
The library queries a database; it does not search itself on the storage media, so the speed improvement by restricting the folder in the query is neglectable. My suggestion: get the map with all files, then filter the result folder by folder (if m.Location = "myfolder" etc.).


getEmbeddedPicture is in API 10.
aha good suggestion thank u , so is that possible to include a function for retreiving covers in the next update?
 

Mrjoey

Active Member
Licensed User
Longtime User
Hello again , im sorry for bothering , but im stuck in here , i really need ur suggestions :
im creating a map inside service_create
B4X:
MapSongs = MB.GetMediaAudioList(True,"artist COLLATE UNICODE, title COLLATE UNICODE")
and then creating a list of IDs and then creating all available cover images and put them in a folder to access them later , inside a loop and it called once:
B4X:
For i = 0 To (MapSongs.Size/9) - 1
list created
images created
next
now im planning to use ur library "cache" and fill all images to it , to maintain memory since i got lots off outofmemory errors but i also have a idea to call this loop when the mediastore has changed(to prevent calling the loop everytime the service starts , because it may take longer if there is lots of media files to scan) like added a new song or deleted a song but i didnt find on the forum sush intent function , all i found is u can force mediastore to refresh but i didnt find if mediastore has refreshed by OS and an event raised .so im thinking to create a disk cache and then load the images when needed and then delete memory cache when finish.
what size do u suggest for images to be filled in cache , and if the number is limited , how many images can i cache cz im reading in ur project that disk cache is about 2mb
so is my plan efficient that way? is there a better plan to do sush thing?i really respect ur experience and any suggestions are appreciated thank u man :)
 

Informatix

Expert
Licensed User
Longtime User
all i found is u can force mediastore to refresh but i didnt find if mediastore has refreshed by OS and an event raised

Keep a list of files in your app (in a database for better performance) and compare it to the list returned by the library. So you can know whether there are new or deleted files and you can update your cache accordingly.

what size do u suggest for images to be filled in cache , and if the number is limited , how many images can i cache cz im reading in ur project that disk cache is about 2mb

It depends strongly on the quality that you want for your images in cache. Usually there's no reason to store images bigger than the screen resolution, so the first thing should be to resize them before storing them in cache. If they are saved in JPG format, you lose a bit of quality but you save a lot of space and you can put plenty of them on disk. The second thing to do is to look at their size in cache and see how much space you want to take for the whole folder (that could be a setting in your app so the user is free to allocate a lot of space or not). Some users will not be happy if you take too much space of their storage media, so stay moderate. 40-50 MB is enough for most uses.

so is my plan efficient that way? is there a better plan to do sush thing?i really respect ur experience and any suggestions are appreciated thank u man :)

I don't know exactly what you want to do so it's hard to tell (a cache in itself is not a solution to avoid Out of Memory errors) but you will be rarely wrong by using a cache.
 

Informatix

Expert
Licensed User
Longtime User
I need know the last 10 photos taken by camera, can I do whit GetMediaImageList and Sort method?
Yes, but as the media database collects data from all your media files, you have to distinguish between your pictures coming from the camera and the other pictures on your phone. Usually, they are stored in a specific folder (e.g. DCIM/camera).
To reverse the order of the sort, you can either read the result of GetMediaImageList starting from the last value of the map (For i = (myMap.Size / 7) - 1 To 0 Step -1) or use the keyword DESC in the SortCol parameter (this parameter is pasted after ORDER BY in a SQL query).
 

Levisvv

Member
Licensed User
Longtime User
I downloaded this sample: MediaBrowser v1.21.zip and compiled and sent it to my Samsung Galaxy S5.
I just showed a spinning hourglass type icon and did nothing.
I edit the buttons to show only images and still this library/sample seems to do nothing?
What can I be doing wrong?

I need an easy way to browse all images on my device and pick an image to load.? Any ideas how to do this easily?
 

Informatix

Expert
Licensed User
Longtime User
I downloaded this sample: MediaBrowser v1.21.zip and compiled and sent it to my Samsung Galaxy S5.
I just showed a spinning hourglass type icon and did nothing.
I edit the buttons to show only images and still this library/sample seems to do nothing?
What can I be doing wrong?

I need an easy way to browse all images on my device and pick an image to load.? Any ideas how to do this easily?
It works fine but you have maybe a huge number of media files on your card so the demo needs some time before displaying them. The delay is due to the Scrollview showing the files, not to the lib. You can check how many files have been found in the DB by logging the size of the map returned by MB.GetMediaAudioList or MB.GetMediaImageList.
 

Mrjoey

Active Member
Licensed User
Longtime User
hey , i recently copied a mp4 file to my music folder but is not recognized , i would like to know what file extentions are recognised by MB? thank u and how to solve this problem.
 

Informatix

Expert
Licensed User
Longtime User
hey , i recently copied a mp4 file to my music folder but is not recognized , i would like to know what file extentions are recognised by MB? thank u and how to solve this problem.
It depends on the OS, not on the library. Here are the supported formats of Android:
http://developer.android.com/guide/appendix/media-formats.html
A MP4 file should be recognized. Did you restart your device? (the database is updated either by a media application, or by rebooting the device)
 

ibra939

Active Member
Licensed User
Longtime User
Awesome, thank you!:D
 

Robert Valentino

Well-Known Member
Licensed User
Longtime User
is it possible to create a MediaSession using MediaBrowser?

I have been trying for sometime to have control over my Car Audio while playing MP3 files and according to this article: http://developer.android.com/training/auto/audio/index.html

I need a MediaBrowserService (which I believe your MediaBrowser is) and a MediaSession

B4X:
Enable Playback Control

Auto devices use MediaSession objects to pass playback control commands to an app that is providing audio services. Your audio app must create an instance of this object to pass to the dashboard device and implement callback methods to enable remote control of audio playback. 

Register a media session

An Auto device using your app as audio service needs to obtain a MediaSession object from your app. The Auto device uses the session object to send playback commands requested by the Auto user back to your app.

When you initialize your browser service, you register that session object with your MediaBrowserService by calling the setSessionToken() method. This step allows clients such as an Auto device to retrieve that object by calling your browser service's getSessionToken() method.

In your browser service's onCreate() method, create a MediaSession. You can then query the MediaSession to get its token, and register the token with your browser service:

Can you add this feature?
 

mlc

Active Member
Licensed User
Longtime User
Hello Informatix,

Thank you for this wonderful library. Works great.

I use it to show pictures and videos on a web page, each item has a checkbox with an id. (The id returned by your library)
I use that id to find the item on the server (delete, etc), but I can not find pictures and videos through the id, location only.

Please, would be possible add these 2 methods?

GetImageFileInfoByID (External AsBoolean, ID AsLong) As Map
GetVideoFileInfoByID (External AsBoolean, ID AsLong) As Map

Thanks again
 

Informatix

Expert
Licensed User
Longtime User
Hello Informatix,

Thank you for this wonderful library. Works great.

I use it to show pictures and videos on a web page, each item has a checkbox with an id. (The id returned by your library)
I use that id to find the item on the server (delete, etc), but I can not find pictures and videos through the id, location only.

Please, would be possible add these 2 methods?

GetImageFileInfoByID (External AsBoolean, ID AsLong) As Map
GetVideoFileInfoByID
(External AsBoolean, ID AsLong) As Map

Thanks again
I don't have enough time to do that currently. Maybe some day.
 
Top