1

I'm creating a music player that populates an array list with song objects. Each song object has a series of attributes. One of those attributes is the album-art URI.

This is the line of code where I assign the URI attribute to the song object.

songObject.albumArtURI = GetAlbumArtURI(albumID); 

Here is the string value of albumID

Log.v("TAG",String.valueOf(albumID)); // prints [Ljava.lang.String;@44ce53d 

When I pass albumID to GetAlbumArtURI() method

private String GetAlbumArtURI(String[] albumID){

    final Cursor mCursor = getContentResolver().query(
            MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, 
            new String[] {MediaStore.Audio.Albums.ALBUM_ART}, 
            MediaStore.Audio.Albums.ALBUM_ID + "=?", 
            albumID, // Error 
            null
    );

    return mCursor.getString(0);

}

I get this error:

no such column: album_id (code 1)
while compiling: 
SELECT album_art FROM album_info WHERE (album_id=?)

The error essentially says that table album_info does not contain album_id column. But according to the documenation, album_info does have such a column.

the_prole
  • 8,275
  • 16
  • 78
  • 163
  • @jyanks I am not creating tables. I am accessing meta data tables. They should already be there. – the_prole Oct 15 '15 at 02:01
  • Sorry, disregard my previous comment. Can you try `MediaStore.Audio.Albums._ID + "=?"` – jyanks Oct 15 '15 at 02:05
  • That gives me this error `android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1` which I think is described [here](http://stackoverflow.com/questions/21996228/mediastore-audio-albums-album-id-invalid-column) so I think my syntax is correct... I posted the string value of `albumID` Does it look correct to you? – the_prole Oct 15 '15 at 02:21
  • Is there any effect if you add the album_id field to the projection array? – jyanks Oct 15 '15 at 02:28
  • @jyanks nope. I get the same error. – the_prole Oct 15 '15 at 02:38
  • Where is that album id coming from? I have the code running here as well and it looks like that -1 requested error is a result of there being no results returned in the cursor (if you do `if(cursor.moveToFirst() && cursor.getCount() > 0)` it'll return false) – jyanks Oct 15 '15 at 02:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92334/discussion-between-jyanks-and-the-prole). – jyanks Oct 15 '15 at 02:53

1 Answers1

4

So there's a few issues causing your query to return nothing and throw that error.

  1. MediaStore.Audio.Albums.ALBUM_ID is not the column you want to reference. You should be using MediaStore.Audio.Albums._ID.

  2. You need to move your cursor's read position to the first position when you get results, if possible. Doing otherwise will result in you never getting the results you need

  3. The way that MediaStore works on android is that you have to register the media files that you want the OS to know about - this isn't automatic. You need to implement something similar to the SingleMediaScanner described in this thread

Here is the working bit of code that I have written:

try {
        final Cursor mCursor = getContentResolver().query(
                MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
                new String[] {MediaStore.Audio.Albums.ALBUM_ART},
                MediaStore.Audio.Albums._ID + "=?",
                null,
                null
        );

        // You need to check if there are results in your cursor. 
        // This is like saying if(mCursor.getCount() > 0)
        if(mCursor.moveToFirst()) {
            return mCursor.getString(mCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
        } else {
            return "";
        }
    } catch (Exception e) {
        Log.e(this.getClass().getSimpleName(),e.getMessage());
    } 

When you have called that code, you're assuming that the MediaStore on your device knows about the music files you've downloaded or added. You can definitely implement a BroadcastReceiver to capture system events like files being added, but for this answer I'm just going to show how you account for one known file. You could also expand this to search an entire directory by adding to the onMediaScannerConnected(...) method.

If you implement the SingleMediaScanner file found here you can then just do:

    File file = new File(Environment.getExternalStorageDirectory() + "/Download/1.mp3");
    SingleMediaScanner singleMediaScanner = new SingleMediaScanner(this, file);

And it will register the media file in your MediaStore. At that point, you should be able to get results back from your query above. If you are having doubts of whether or not the songs are being registered, you can check to see if any records have been added at all by changing your mCursor call to this (to get all the results in the media store) and then iterating through them:

 final Cursor mCursor = getContentResolver().query(
                MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
                null,
                null,
                null,
                null
        );
Community
  • 1
  • 1
jyanks
  • 2,356
  • 1
  • 19
  • 36
  • How can I test if an individual media file has been registered with Media-store so I don't have to call `SingleMediaScanner()` on each and every file every-time the music app is re-opened? – the_prole Oct 15 '15 at 07:49
  • Really, you can check the media store for that file via the contentResolver query that you have above. I realize that's not ideal, so you could put all that discovery code into a background service or something like that and notify the UI layer when there are new files detected. – jyanks Oct 15 '15 at 12:18
  • Do you think you could help me with this [question](http://stackoverflow.com/questions/33751762/unable-to-return-all-album-uris-with-content-resolver/33754002#33754002) which is related to the same topic. Thanks. – the_prole Nov 18 '15 at 03:22