Media Store for Audio

We explored using the MediaStore for images early on in this book. Much of what we learned can be leveraged for the storage and retrieval of other types of media, including audio. In order to provide a robust mechanism for browsing and searching for audio, Android includes a MediaStore.Audio package, which defines the standard content provider.

Accessing Audio from the MediaStore

Accessing audio files that are stored using the MediaStore provider is consistent with our previous uses of the MediaStore. In this case, we'll be using the android.provider.MediaStore.Audio package.

One of the easiest ways to illustrate the use of the MediaStore for audio is to go through a sample application. The following code creates an activity that queries the MediaStore for any audio file and simply plays the first one returned.

package com.apress.proandroidmedia.ch5.audioplayer;

import java.io.File;

import android.app.Activity;

import android.content.Intent;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.util.Log;

import android.provider.MediaStore;

public class AudioPlayer extends Activity {

^Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

To use the MediaStore, we need to specify which data we want returned. We do this by creating an array of strings using the constants located in the android.provider.MediaStore.Audio.Media class. Those constants are all of the standard fields that are saved in the MediaStore for use with audio.

In this case, we are asking for the DATA column, which contains the path to the actual audio file. We are also asking for the internal ID, the Title, Display Name, MIME-Type, Artist, Album, and which type of audio file it is, alarm, music, ring tone, or notification type.

Other columns such as date added (DATE_ADDED), date modified (DATE_MODIFIED), file size (SIZE), and so on are available as well.

MediaStore.Audio.Media.DATA,

MediaStore.Audio.Media._ID,

MediaStore.Audio.Media.TITLE,

MediaStore.Audio.Media.DISPLAY_NAME,

MediaStore.Audio.Media.MIME_TYPE,

MediaStore.Audio.Media.ARTIST,

MediaStore.Audio.Media.ALBUM,

MediaStore.Audio.Media.IS_RINGTONE,

MediaStore.Audio.Media.IS_ALARM,

MediaStore.Audio.Media.IS_MUSIC,

MediaStore.Audio.Media.IS_NOTIFICATION

We query the MediaStore by calling the managedQuery method in Activity. The managedQuery method takes in the Uri for the content provider, in this case, the audio MediaStore, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI. This Uri specifies that we want audio stored on the SD card. If we wanted audio files that are stored in the internal memory, we would use android.provider.MediaStore.Audio.Media.INTERNAL_CONTENT_URI.

In addition to the Uri to the MediaStore, the managedQuery method takes in the array of columns that we want returned, an SQL WHERE clause, the values for the WHERE clause, and an SQL ORDER BY clause.

In this example, we aren't using the WHERE and ORDER BY clauses, so we'll pass in null for those arguments.

Cursor cursor = managedOuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,^

columns, null, null, null);

The managedQuery method returns a Cursor object. The Cursor class allows interaction with a dataset returned from a database query.

The first thing we'll do is create a couple of variables to hold the column numbers for some of the columns we want to access from the results. This isn't absolutely necessary, but it is nice to have the index around so we don't have to call the method on the Cursor object each time we need them. The way we get them is to pass in the constant value for the column we want to the getColumnIndex method on the Cursor.

int fileColumn = cursor.getColumnIndex (MediaStore.Audio.Media.DATA);

The first one is the index of the column containing the path to the actual audio file. We got the foregoing index by passing in the constant that represents that column, android.provider.MediaStore.Audio.Media.DATA.

Next we are getting a couple of other indexes, not all of which we are actually using, so the extras are here merely for illustration purposes.

int titleColumn = cursor.getColumnlndex (MediaStore.Audio.Media.TITLE);

int displayColumn = cursor.getColumnlndex (MediaStore.Audio.Media.DISPLAY_NAME);

int mimeTypeColumn = cursor.getColumnlndex (MediaStore.Audio.Media.MIME_TYPE);

int titleColumn = cursor.getColumnlndex (MediaStore.Audio.Media.TITLE);

int displayColumn = cursor.getColumnlndex (MediaStore.Audio.Media.DISPLAY_NAME);

int mimeTypeColumn = cursor.getColumnlndex (MediaStore.Audio.Media.MIME_TYPE);

The data returned by the MediaStore available in the Cursor is organized in rows as well as by columns. We can get the first result returned by calling the moveToFirst method and retrieving the results from there. The method will return a Boolean false if no rows are returned, so we can wrap it in an if statement to make sure there is data.

if (cursor.moveToFirst()) {

To get the actual data, we call one of the "get" methods on the Cursor and pass in the index for the column we want to retrieve. If the data is expected to be a String, we call getString. If it is expected to be an integer, we call getlnt. There are corresponding "get" methods for all of the primitive data types.

String audioFilePath = cursor.getString(fileColumn); String mimeType = cursor.getString(mimeTypeColumn);

Log.v("AUDIOPLAYER",audioFilePath); Log.v("AUDIOPLAYER",mimeType);

Once we have the path to the file and the MIME type, we can use those to construct the intent to launch the built-in audio player application and play that file. (Alternatively we could use the MediaPlayer class as illustrated previously to play the audio file directly.) In order to turn the path to the audio file into a Uri that we can pass into the intent, we construct a File object and use the Uri.fromFile method to get the Uri. There are other ways to do the same, but this is probably the most straightforward.

Intent intent = new Intent(android.content.Intent.ACTION_VIEW); File newFile = new File(audioFilePath); intent.setDataAndType(Uri.fromFile(newFile), mimeType); startActivity(intent);

That finishes off our basic illustration of using the MediaStore for audio.

Now, let's take it a step further and create an application that allows us to narrow down the results returned and browse them, allowing the user to select the audio file to play.

Browsing Audio in the MediaStore

Audio files, in particular music files, can be found by album, artist, and genre as well as directly in the MediaStore. Each of these has an Uri that can be used with a managedOuery to search with.

android.provider.MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI

■ Artist: android.provider.MediaStore.Artists.EXTERNAL_CONTENT_URI

■ Genre: android.provider.MediaStore.Genres.EXTERNAL_CONTENT_URI

Here is how you would use the album Uri to query for all of the albums on the device:

String[] columns = { android.provider.MediaStore.Audio.Albums._ID, android.provider.MediaStore.Audio.Albums.ALBUM}; Cursor cursor = managedOuery(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, columns,^ null, null, null); if (cursor != null) {

while (cursor.moveToNext()) { Log.v("OUTPUT", cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM)));

In the foregoing code snippet, you see that we are asking the MediaStore to return the _ID and the ALBUM columns. The ALBUM constant indicates that we want the name of the album returned. Other columns available are listed in the android.provider.MediaStore.Audio.Albums class and are inherited from android.provider.BaseColumns and android.provider.MediaStore.Audio.AlbumColumns.

We are calling the managedOuery method giving just the Uri and the list of columns, leaving the other parameters as null. This will give us all of the albums available on the device.

Finally, we are outputting the list of albums. To iterate through the list returned inside the Cursor object, we first check that the Cursor contains results (cursor ! = null) and then use the moveToNext method.

Album Browsing App Example

What follows is an example that uses the foregoing as a starting point to allow the user to see the names of all of the albums. The user can indicate which album he or she would like to see the songs on. It will then present the list of songs, and if the user selects one of those, it will play that song.

package com.apress.proandroidmedia.ch5.audiobrowser;

import java.io.File;

import android.app.ListActivity;

import android.content.Intent;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.provider.MediaStore;

import android.util.Log;

import android.view.View;

import android.widget.ListView;

import android.widget.SimpleCursorAdapter;

Instead of extending a generic activity, let's extend ListActivity. This allows us to present and manage a basic ListView.

public class AudioBrowser extends ListActivity {

Cursor cursor;

Let's create a couple of constants that will help us keep track of where the user is in the application and respond appropriately when the user performs an action. This will be kept track of in the currentState variable that is initially set to STATE_SELECT_ALBUM.

public static int STATE_SELECT_ALBUM = 0; public static int STATE_SELECT_SONG = 1;

int currentState = STATE_SELECT_ALBUM;

Just like a normal activity, we have an onCreate method where we can perform the initial commands.

^Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

After setting the layout (via the main.xml layout XML file), we create an array of Strings that represents the columns we want returned from the MediaStore when we run our query. In this case, it is the same as the foregoing snippet of code—we want the _ID and the name of the album, ALBUM. Both are constants in the MediaStore.Audio.Albums class.

android.provider.MediaStore.Audio.Albums._ID, android.provider.MediaStore.Audio.Albums.ALBUM

We call the managedOuery method with only the Uri representing the album search and the columns, leaving everything else null. This should give us a list of all of the albums available.

cursor = managedOuery(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, columns, null, null, null);

Once we do this, we are returned a Cursor object that contains the results of our query.

Since we are using a ListActivity, we have the ability to have it automagically manage the list of data for us. We can use the setListAdapter method to bind our Cursor object to ListView.

First we create an array of Strings that is the name of the columns in the Cursor that we want displayed. In our case, we just want the name of the album— MediaStore.Audio.Albums.ALBUM is our constant for that.

Next we list the View objects that will display the data from those columns. Since we just have one column, we need only one View object. It is android.R.id.textl. This View is available to us, as it is part of the android.R.layout.simple_list_item_1 layout that we'll be using in the next step.

Last we call the setListAdapter method, passing in a SimpleCursorAdapter, which we are creating inline. The SimpleCursorAdapter is a simple adapter from a Cursor object containing data to a ListActivity. In creating the SimpleCursoryAdapter, we pass in our activity (this) as the Context, a standard ListView layout that is already defined for us (android.R.layout.simple_list_item_1), the Cursor object containing the data, and the two arrays we just defined.

String[] displayFields = new String[] {MediaStore.Audio.Albums.ALBUM}; int[] displayViews = new int[] {android.R.id.textl}; setListAdapter(new SimpleCursorAdapter(this,^

android.R.layout.simple_list_item_1, cursor, displayFields,^

displayViews)); }

If we were to run this as is, we would get a simple list of the albums available on our device as shown in Figure 5-3. We are going to take it a step further, though, and allow the user to select an album.

Audio Browser

+8 -1

Responses

  • Sabine
    How to use where clause with mediastore in android?
    6 years ago
  • meeri
    How to get particular media file using mediastore in android?
    6 years ago
  • joel
    How to modify MediaStore.Audio.AlbumColumns?
    2 years ago
  • zufan
    How to get audio title , id , genre , artist from mediastore?
    2 years ago
  • Sabine
    How to get audio files through mediastore?
    1 year ago
  • hyiab
    How to play song from managed query?
    1 year ago
  • asmara
    How to play music from media store in android?
    10 months ago
  • Nico
    How to play audio/video after displaying through MediaStore.Media?
    1 month ago

Post a comment