1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.musicplayer;
18 
19 import android.content.ContentResolver;
20 import android.content.ContentUris;
21 import android.database.Cursor;
22 import android.net.Uri;
23 import android.provider.MediaStore;
24 import android.util.Log;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Random;
29 
30 /**
31  * Retrieves and organizes media to play. Before being used, you must call {@link #prepare()},
32  * which will retrieve all of the music on the user's device (by performing a query on a content
33  * resolver). After that, it's ready to retrieve a random song, with its title and URI, upon
34  * request.
35  */
36 public class MusicRetriever {
37     final String TAG = "MusicRetriever";
38 
39     ContentResolver mContentResolver;
40 
41     // the items (songs) we have queried
42     List<Item> mItems = new ArrayList<Item>();
43 
44     Random mRandom = new Random();
45 
MusicRetriever(ContentResolver cr)46     public MusicRetriever(ContentResolver cr) {
47         mContentResolver = cr;
48     }
49 
50     /**
51      * Loads music data. This method may take long, so be sure to call it asynchronously without
52      * blocking the main thread.
53      */
prepare()54     public void prepare() {
55         Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
56         Log.i(TAG, "Querying media...");
57         Log.i(TAG, "URI: " + uri.toString());
58 
59         // Perform a query on the content resolver. The URI we're passing specifies that we
60         // want to query for all audio media on external storage (e.g. SD card)
61         Cursor cur = mContentResolver.query(uri, null,
62                 MediaStore.Audio.Media.IS_MUSIC + " = 1", null, null);
63         Log.i(TAG, "Query finished. " + (cur == null ? "Returned NULL." : "Returned a cursor."));
64 
65         if (cur == null) {
66             // Query failed...
67             Log.e(TAG, "Failed to retrieve music: cursor is null :-(");
68             return;
69         }
70         if (!cur.moveToFirst()) {
71             // Nothing to query. There is no music on the device. How boring.
72             Log.e(TAG, "Failed to move cursor to first row (no query results).");
73             return;
74         }
75 
76         Log.i(TAG, "Listing...");
77 
78         // retrieve the indices of the columns where the ID, title, etc. of the song are
79         int artistColumn = cur.getColumnIndex(MediaStore.Audio.Media.ARTIST);
80         int titleColumn = cur.getColumnIndex(MediaStore.Audio.Media.TITLE);
81         int albumColumn = cur.getColumnIndex(MediaStore.Audio.Media.ALBUM);
82         int durationColumn = cur.getColumnIndex(MediaStore.Audio.Media.DURATION);
83         int idColumn = cur.getColumnIndex(MediaStore.Audio.Media._ID);
84 
85         Log.i(TAG, "Title column index: " + String.valueOf(titleColumn));
86         Log.i(TAG, "ID column index: " + String.valueOf(titleColumn));
87 
88         // add each song to mItems
89         do {
90             Log.i(TAG, "ID: " + cur.getString(idColumn) + " Title: " + cur.getString(titleColumn));
91             mItems.add(new Item(
92                     cur.getLong(idColumn),
93                     cur.getString(artistColumn),
94                     cur.getString(titleColumn),
95                     cur.getString(albumColumn),
96                     cur.getLong(durationColumn)));
97         } while (cur.moveToNext());
98 
99         Log.i(TAG, "Done querying media. MusicRetriever is ready.");
100     }
101 
getContentResolver()102     public ContentResolver getContentResolver() {
103         return mContentResolver;
104     }
105 
106     /** Returns a random Item. If there are no items available, returns null. */
getRandomItem()107     public Item getRandomItem() {
108         if (mItems.size() <= 0) return null;
109         return mItems.get(mRandom.nextInt(mItems.size()));
110     }
111 
112     public static class Item {
113         long id;
114         String artist;
115         String title;
116         String album;
117         long duration;
118 
Item(long id, String artist, String title, String album, long duration)119         public Item(long id, String artist, String title, String album, long duration) {
120             this.id = id;
121             this.artist = artist;
122             this.title = title;
123             this.album = album;
124             this.duration = duration;
125         }
126 
getId()127         public long getId() {
128             return id;
129         }
130 
getArtist()131         public String getArtist() {
132             return artist;
133         }
134 
getTitle()135         public String getTitle() {
136             return title;
137         }
138 
getAlbum()139         public String getAlbum() {
140             return album;
141         }
142 
getDuration()143         public long getDuration() {
144             return duration;
145         }
146 
getURI()147         public Uri getURI() {
148             return ContentUris.withAppendedId(
149                     android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
150         }
151     }
152 }
153