Thursday, June 23, 2011

How to query for music on Android



Within my simple music alarm application, I needed a way to retrieve all the artists, albums and songs on the phone. Unsure of whether there was a service there already to do so, I searched about Google how to do this. The lack of any complete A-Z articles on the subject led me to write this...

In Android, all of our music information (song title, track number, album art, artist name, etc.) is stored in a system music database. There are several tables (genres, artists, playlists, audio and more) so it is important to know what you want to find before you can think of where to look. We can query these tables through the ContextResolver object found in our Context object (of an Activity, Service, BroadcastReceiver, etc.).

I have created a small example to query our SD card for all the songs, artists and albums found on it.

Download the Source Code!!

Not sure how to put music on the SD card in the Android emulator? Check out my previous blog post to learn how to do so.

Below is a test method I wrote to collect the names of every album stored on the phone. Let's look at the code and the comments. I'll explain what's remaining afterwards.

public void collectAllAlbums()
{
// the cursor we will use to iterate over the db results
Cursor cursor = null;

// the list of columns our search relates to
final String[] projection = new String[] {MediaStore.Audio.AlbumColumns.ALBUM };

// how we want to sort our results
final String sortOrder = MediaStore.Audio.AlbumColumns.ALBUM + " COLLATE LOCALIZED ASC";
try
{
// the uri of the table that we want to query
Uri uri = android.provider.MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;

// we now launch the query (be sure not to do this in the UI thread should it take a while)
cursor = mainContext.getContentResolver().query(uri, projection, null, null, sortOrder);
if (cursor != null)
{
int i = 0;
allAlbums = new String[cursor.getCount()];
cursor.moveToFirst();
while (!cursor.isAfterLast())
{
// get the 1st col in our returned data set (AlbumColumns.ALBUM)
allAlbums[i++] = cursor.getString(0);
cursor.moveToNext();
}
}
}
finally
{
if (cursor != null)
{
cursor.close();
}
}
}

So, what just happened?
  • We query the data table located at the Uri provided for all the albums in the table. All the important stuff is in ContextResolver.query(...). Check out the Android documentation on the subject for details.
  • We use a cursor to iterate over the data set returned. The cursor uses resources so you must always close the cursor when you are done with it (hence the try/finally block). As of API 11 (Android 3.0 - Honeycomb), using a CursorLoader will take care of deactivating the Cursor when the activity closes. However, if not using a CursorLoader, it is wise to close the Cursor when done with it.
  • We call getString(0) on the cursor. This will return the value of a given column in the current data row. You must know which type you are expecting, because there is getString, getLong, getDouble, etc..
Queries may take a while. It 's a pretty good idea to launch them in a background thread and once the query is done, post it back to the UI thread to update what it needs to. I do just that in the example I've included.

You can also check in my example code how long the queries take. You should not use null as your projection string in the query. The String[] projection declares which columns of the table you want returned. Passing null will return all the columns, which is very inefficient (unless that is what you want to do). Play with the example and see for yourself.





The last thing I should add: sometimes you'll have to use other data tables to find the information you're looking for. I know that in the Audio table Columns, you won't find the genre of the song unfortunately. This information is stored in a separate table, but querying its table is just the same as in this example. Use the correct Uri, know which columns you want returned (build the String[] projection), build the selection (sql WHERE) string accordingly and the ordering string (sql ORDER BY).

Happy querying!

2 comments:

  1. I have a android phone online store and i want to create some blogs to improve my traffic but i was see your blogs
    and i was happy to get some idea to your blogs thanks a lot you create a good blogs i hope you do more blogs ^^

    ReplyDelete