Add support for playlist playback
No support for creation or editing yet
This commit is contained in:
parent
7090c468aa
commit
fad3b1160b
BIN
res/drawable/ic_tab_playlists_selected.png
Normal file
BIN
res/drawable/ic_tab_playlists_selected.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 814 B |
BIN
res/drawable/ic_tab_playlists_unselected.png
Normal file
BIN
res/drawable/ic_tab_playlists_unselected.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 477 B |
9
res/drawable/tab_playlists.xml
Normal file
9
res/drawable/tab_playlists.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:state_selected="true"
|
||||||
|
android:state_pressed="false"
|
||||||
|
android:drawable="@drawable/ic_tab_playlists_selected" />
|
||||||
|
<item
|
||||||
|
android:drawable="@drawable/ic_tab_playlists_unselected" />
|
||||||
|
</selector>
|
@ -57,6 +57,12 @@
|
|||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:divider="@null"
|
android:divider="@null"
|
||||||
android:fastScrollEnabled="true" />
|
android:fastScrollEnabled="true" />
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/playlist_list"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:divider="@null"
|
||||||
|
android:fastScrollEnabled="true" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</TabHost>
|
</TabHost>
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
<string name="artists">Artists</string>
|
<string name="artists">Artists</string>
|
||||||
<string name="albums">Albums</string>
|
<string name="albums">Albums</string>
|
||||||
<string name="songs">Songs</string>
|
<string name="songs">Songs</string>
|
||||||
|
<string name="playlists">Playlists</string>
|
||||||
|
|
||||||
<string name="none">None</string>
|
<string name="none">None</string>
|
||||||
|
|
||||||
|
@ -55,16 +55,11 @@ import android.widget.FilterQueryProvider;
|
|||||||
*/
|
*/
|
||||||
public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
||||||
/**
|
/**
|
||||||
* Type indicating that MediaStore.Audio.Artists should be used as the
|
* The type of media represented by this adapter. Must be one of the
|
||||||
* provider backing this adapter.
|
* Song.FIELD_* constants. Determines which content provider to query for
|
||||||
|
* media and what fields to display.
|
||||||
*/
|
*/
|
||||||
public static final int TYPE_ARTIST = 1;
|
int mType;
|
||||||
/**
|
|
||||||
* Type indicating that MediaStore.Audio.Albums should be used as the
|
|
||||||
* adapter backing this adapter.
|
|
||||||
*/
|
|
||||||
public static final int TYPE_ALBUM = 2;
|
|
||||||
|
|
||||||
Uri mStore;
|
Uri mStore;
|
||||||
String[] mFields;
|
String[] mFields;
|
||||||
private String[] mFieldKeys;
|
private String[] mFieldKeys;
|
||||||
@ -73,16 +68,51 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
private CharSequence mConstraint;
|
private CharSequence mConstraint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform required setup during construction. See constructors for
|
* Construct a MediaAdapter representing the given <code>type</code> of
|
||||||
* details.
|
* media.
|
||||||
|
*
|
||||||
|
* @param context A Context to use
|
||||||
|
* @param type The type of media to represent. Must be one of the
|
||||||
|
* Song.TYPE_* constants. This determines which content provider to query
|
||||||
|
* and what fields to display in the views.
|
||||||
|
* @param expandable Whether an expand arrow should be shown to the right
|
||||||
|
* of the views' text
|
||||||
|
* @param requery If true, automatically update the adapter when the
|
||||||
|
* provider backing it changes
|
||||||
*/
|
*/
|
||||||
private void init(Context context, Uri store, String[] fields, String[] fieldKeys, boolean expandable)
|
public MediaAdapter(Context context, int type, boolean expandable, boolean requery)
|
||||||
{
|
{
|
||||||
mStore = store;
|
super(context, null, requery);
|
||||||
mFields = fields;
|
|
||||||
mFieldKeys = fieldKeys;
|
mType = type;
|
||||||
mExpandable = expandable;
|
mExpandable = expandable;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Song.TYPE_ARTIST:
|
||||||
|
mStore = MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI;
|
||||||
|
mFields = new String[] { MediaStore.Audio.Artists.ARTIST };
|
||||||
|
mFieldKeys = new String[] { MediaStore.Audio.Artists.ARTIST_KEY };
|
||||||
|
break;
|
||||||
|
case Song.TYPE_ALBUM:
|
||||||
|
mStore = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
|
||||||
|
mFields = new String[] { MediaStore.Audio.Albums.ARTIST, MediaStore.Audio.Albums.ALBUM };
|
||||||
|
// Why is there no artist_key column constant in the album MediaStore? The column does seem to exist.
|
||||||
|
mFieldKeys = new String[] { "artist_key", MediaStore.Audio.Albums.ALBUM_KEY };
|
||||||
|
break;
|
||||||
|
case Song.TYPE_SONG:
|
||||||
|
mStore = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
mFields = new String[] { MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.TITLE };
|
||||||
|
mFieldKeys = new String[] { MediaStore.Audio.Media.ARTIST_KEY, MediaStore.Audio.Media.ALBUM_KEY, MediaStore.Audio.Media.TITLE_KEY };
|
||||||
|
break;
|
||||||
|
case Song.TYPE_PLAYLIST:
|
||||||
|
mStore = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
||||||
|
mFields = new String[] { MediaStore.Audio.Playlists.NAME };
|
||||||
|
mFieldKeys = null;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid value for type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
setFilterQueryProvider(this);
|
setFilterQueryProvider(this);
|
||||||
requery();
|
requery();
|
||||||
|
|
||||||
@ -97,65 +127,6 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a MediaAdapter representing an arbitrary media content
|
|
||||||
* provider.
|
|
||||||
*
|
|
||||||
* @param context A Context to use
|
|
||||||
* @param store The external content uri of the provider
|
|
||||||
* @param fields The fields to use in the provider. The last field will be
|
|
||||||
* displayed as the first line in views. If more than one field is given,
|
|
||||||
* the first field will be displayed as the bottom line.
|
|
||||||
* @param fieldKeys The sorting keys corresponding to each field from
|
|
||||||
* <code>fields</code>. Used for filtering.
|
|
||||||
* @param expandable Whether an expand arrow should be shown to the right
|
|
||||||
* of the views' text
|
|
||||||
* @param requery If true, automatically update the adapter when the
|
|
||||||
* provider backing it changes
|
|
||||||
*/
|
|
||||||
protected MediaAdapter(Context context, Uri store, String[] fields, String[] fieldKeys, boolean expandable, boolean requery)
|
|
||||||
{
|
|
||||||
super(context, null, requery);
|
|
||||||
init(context, store, fields, fieldKeys, expandable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a MediaAdapter representing the given <code>type</code> of
|
|
||||||
* media.
|
|
||||||
*
|
|
||||||
* @param context A Context to use
|
|
||||||
* @param type The type of media; one of TYPE_ALBUM or TYPE_ARTIST
|
|
||||||
* @param expandable Whether an expand arrow should be shown to the right
|
|
||||||
* of the views' text
|
|
||||||
* @param requery If true, automatically update the adapter when the
|
|
||||||
* provider backing it changes
|
|
||||||
*/
|
|
||||||
public MediaAdapter(Context context, int type, boolean expandable, boolean requery)
|
|
||||||
{
|
|
||||||
super(context, null, requery);
|
|
||||||
|
|
||||||
Uri store;
|
|
||||||
String[] fields;
|
|
||||||
String[] fieldKeys;
|
|
||||||
switch (type) {
|
|
||||||
case TYPE_ARTIST:
|
|
||||||
store = MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI;
|
|
||||||
fields = new String[] { MediaStore.Audio.Artists.ARTIST };
|
|
||||||
fieldKeys = new String[] { MediaStore.Audio.Artists.ARTIST_KEY };
|
|
||||||
break;
|
|
||||||
case TYPE_ALBUM:
|
|
||||||
store = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
|
|
||||||
fields = new String[] { MediaStore.Audio.Albums.ARTIST, MediaStore.Audio.Albums.ALBUM };
|
|
||||||
// Why is there no artist_key column constant in the album MediaStore? The column does seem to exist.
|
|
||||||
fieldKeys = new String[] { "artist_key", MediaStore.Audio.Albums.ALBUM_KEY };
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid value for type: " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
init(context, store, fields, fieldKeys, expandable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void requery()
|
public final void requery()
|
||||||
{
|
{
|
||||||
changeCursor(runQuery(mConstraint));
|
changeCursor(runQuery(mConstraint));
|
||||||
@ -174,7 +145,8 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
|
|
||||||
protected String getSortOrder()
|
protected String getSortOrder()
|
||||||
{
|
{
|
||||||
return mFieldKeys[mFieldKeys.length - 1];
|
String[] source = mFieldKeys == null ? mFields : mFieldKeys;
|
||||||
|
return source[source.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor runQuery(CharSequence constraint)
|
public Cursor runQuery(CharSequence constraint)
|
||||||
@ -201,11 +173,20 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (constraint != null && constraint.length() != 0) {
|
if (constraint != null && constraint.length() != 0) {
|
||||||
String colKey = MediaStore.Audio.keyFor(constraint.toString());
|
String[] needles;
|
||||||
String spaceColKey = DatabaseUtils.getCollationKey(" ");
|
|
||||||
String[] colKeys = colKey.split(spaceColKey);
|
|
||||||
|
|
||||||
int size = colKeys.length;
|
// If we are using sorting keys, we need to change our constraint
|
||||||
|
// into a list of collation keys. Otherwise, just split the
|
||||||
|
// constraint with no modification.
|
||||||
|
if (mFieldKeys != null) {
|
||||||
|
String colKey = MediaStore.Audio.keyFor(constraint.toString());
|
||||||
|
String spaceColKey = DatabaseUtils.getCollationKey(" ");
|
||||||
|
needles = colKey.split(spaceColKey);
|
||||||
|
} else {
|
||||||
|
needles = constraint.toString().split("\\s+");
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = needles.length;
|
||||||
if (limiter != null)
|
if (limiter != null)
|
||||||
++size;
|
++size;
|
||||||
selectionArgs = new String[size];
|
selectionArgs = new String[size];
|
||||||
@ -215,23 +196,23 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String keys = mFieldKeys[0];
|
String[] keySource = mFieldKeys == null ? mFields : mFieldKeys;
|
||||||
for (int j = 1; j != mFieldKeys.length; ++j)
|
String keys = keySource[0];
|
||||||
keys += "||" + mFieldKeys[j];
|
for (int j = 1; j != keySource.length; ++j)
|
||||||
|
keys += "||" + keySource[j];
|
||||||
|
|
||||||
for (int j = 0; j != colKeys.length; ++i, ++j) {
|
for (int j = 0; j != needles.length; ++i, ++j) {
|
||||||
selectionArgs[i] = '%' + colKeys[j] + '%';
|
selectionArgs[i] = '%' + needles[j] + '%';
|
||||||
|
|
||||||
if (j != 0 || selection.length() != 0)
|
if (i != 0)
|
||||||
selection.append(" AND ");
|
selection.append(" AND ");
|
||||||
selection.append(keys);
|
selection.append(keys);
|
||||||
selection.append(" LIKE ?");
|
selection.append(" LIKE ?");
|
||||||
}
|
}
|
||||||
|
} else if (limiter != null) {
|
||||||
|
selectionArgs = new String[] { limiter };
|
||||||
} else {
|
} else {
|
||||||
if (limiter != null)
|
selectionArgs = null;
|
||||||
selectionArgs = new String[] { limiter };
|
|
||||||
else
|
|
||||||
selectionArgs = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] projection;
|
String[] projection;
|
||||||
@ -391,6 +372,15 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider {
|
|||||||
return mId;
|
return mId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of media contained in the adapter containing this
|
||||||
|
* view. Will be one of the Song.TYPE_* constants.
|
||||||
|
*/
|
||||||
|
public int getMediaType()
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
public final String getTitle()
|
public final String getTitle()
|
||||||
{
|
{
|
||||||
return mTitle;
|
return mTitle;
|
||||||
|
@ -45,6 +45,23 @@ public class Song implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final int FLAG_RANDOM = 0x1;
|
public static final int FLAG_RANDOM = 0x1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type indicating an id represents an artist.
|
||||||
|
*/
|
||||||
|
public static final int TYPE_ARTIST = 1;
|
||||||
|
/**
|
||||||
|
* Type indicating an id represents an album.
|
||||||
|
*/
|
||||||
|
public static final int TYPE_ALBUM = 2;
|
||||||
|
/**
|
||||||
|
* Type indicating an id represents a song.
|
||||||
|
*/
|
||||||
|
public static final int TYPE_SONG = 3;
|
||||||
|
/**
|
||||||
|
* Type indicating an id represents a playlist.
|
||||||
|
*/
|
||||||
|
public static final int TYPE_PLAYLIST = 4;
|
||||||
|
|
||||||
private static final String[] FILLED_PROJECTION = {
|
private static final String[] FILLED_PROJECTION = {
|
||||||
MediaStore.Audio.Media._ID,
|
MediaStore.Audio.Media._ID,
|
||||||
MediaStore.Audio.Media.DATA,
|
MediaStore.Audio.Media.DATA,
|
||||||
@ -180,36 +197,77 @@ public class Song implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array containing all the song ids that match the specified parameters
|
* Return a cursor containing the ids of all the songs with artist or
|
||||||
|
* album of the specified id.
|
||||||
*
|
*
|
||||||
* @param type Type the id represent. May be 1, 2 or 3, meaning artist,
|
* @param resolver The ContentResolver to run the query with.
|
||||||
* album or song, respectively.
|
* @param type TYPE_ARTIST or TYPE_ALBUM, indicating the the id represents
|
||||||
* @param id Id of the element
|
* an artist or album
|
||||||
|
* @param id The MediaStore id of the artist or album
|
||||||
*/
|
*/
|
||||||
public static long[] getAllSongIdsWith(int type, long id)
|
private static Cursor getMediaCursor(ContentResolver resolver, int type, long id)
|
||||||
{
|
{
|
||||||
if (type == 3)
|
String selection = '=' + id + " AND " + MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
||||||
return new long[] { id };
|
|
||||||
|
|
||||||
String selection = "=" + id + " AND " + MediaStore.Audio.Media.IS_MUSIC + "!=0";
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 2:
|
case TYPE_ARTIST:
|
||||||
selection = MediaStore.Audio.Media.ALBUM_ID + selection;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
selection = MediaStore.Audio.Media.ARTIST_ID + selection;
|
selection = MediaStore.Audio.Media.ARTIST_ID + selection;
|
||||||
break;
|
break;
|
||||||
|
case TYPE_ALBUM:
|
||||||
|
selection = MediaStore.Audio.Media.ALBUM_ID + selection;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
throw new IllegalArgumentException("Invalid type specified: " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
String[] projection = { MediaStore.Audio.Media._ID };
|
String[] projection = { MediaStore.Audio.Media._ID };
|
||||||
|
|
||||||
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
|
||||||
String sort = MediaStore.Audio.Media.ARTIST_KEY + ',' + MediaStore.Audio.Media.ALBUM_KEY + ',' + MediaStore.Audio.Media.TRACK;
|
String sort = MediaStore.Audio.Media.ARTIST_KEY + ',' + MediaStore.Audio.Media.ALBUM_KEY + ',' + MediaStore.Audio.Media.TRACK;
|
||||||
Cursor cursor = resolver.query(media, projection, selection, null, sort);
|
return resolver.query(media, projection, selection, null, sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a cursor containing the ids of all the songs in the playlist
|
||||||
|
* with the given id.
|
||||||
|
*
|
||||||
|
* @param resolver The ContentResolver to run the query with.
|
||||||
|
* @param id The id of the playlist in MediaStore.Audio.Playlists.
|
||||||
|
*/
|
||||||
|
private static Cursor getPlaylistCursor(ContentResolver resolver, long id)
|
||||||
|
{
|
||||||
|
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", id);
|
||||||
|
String[] projection = new String[] { MediaStore.Audio.Playlists.Members.AUDIO_ID };
|
||||||
|
return resolver.query(uri, projection, null, null,
|
||||||
|
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array containing all the song ids that match the specified parameters
|
||||||
|
*
|
||||||
|
* @param type Type the id represents. Must be one of the Song.TYPE_*
|
||||||
|
* constants.
|
||||||
|
* @param id The id of the element in the MediaStore content provider for
|
||||||
|
* the given type.
|
||||||
|
*/
|
||||||
|
public static long[] getAllSongIdsWith(int type, long id)
|
||||||
|
{
|
||||||
|
ContentResolver resolver = ContextApplication.getContext().getContentResolver();
|
||||||
|
Cursor cursor;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case TYPE_SONG:
|
||||||
|
return new long[] { id };
|
||||||
|
case TYPE_ARTIST:
|
||||||
|
case TYPE_ALBUM:
|
||||||
|
cursor = getMediaCursor(resolver, type, id);
|
||||||
|
break;
|
||||||
|
case TYPE_PLAYLIST:
|
||||||
|
cursor = getPlaylistCursor(resolver, id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Specified type not valid: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
if (cursor == null)
|
if (cursor == null)
|
||||||
return null;
|
return null;
|
||||||
@ -222,7 +280,7 @@ public class Song implements Parcelable {
|
|||||||
for (int i = 0; i != count; ++i) {
|
for (int i = 0; i != count; ++i) {
|
||||||
if (!cursor.moveToNext())
|
if (!cursor.moveToNext())
|
||||||
return null;
|
return null;
|
||||||
songs[i] = cursor.getInt(0);
|
songs[i] = cursor.getLong(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.close();
|
cursor.close();
|
||||||
@ -353,8 +411,8 @@ public class Song implements Parcelable {
|
|||||||
|
|
||||||
if (fileDescriptor != null) {
|
if (fileDescriptor != null) {
|
||||||
// Construct a MediaScanner
|
// Construct a MediaScanner
|
||||||
Class mediaScannerClass = Class.forName("android.media.MediaScanner");
|
Class<?> mediaScannerClass = Class.forName("android.media.MediaScanner");
|
||||||
Constructor mediaScannerConstructor = mediaScannerClass.getDeclaredConstructor(Context.class);
|
Constructor<?> mediaScannerConstructor = mediaScannerClass.getDeclaredConstructor(Context.class);
|
||||||
Object mediaScanner = mediaScannerConstructor.newInstance(ContextApplication.getContext());
|
Object mediaScanner = mediaScannerConstructor.newInstance(ContextApplication.getContext());
|
||||||
|
|
||||||
// Call extractAlbumArt(fileDescriptor)
|
// Call extractAlbumArt(fileDescriptor)
|
||||||
|
@ -38,11 +38,7 @@ public class SongMediaAdapter extends MediaAdapter {
|
|||||||
*/
|
*/
|
||||||
public SongMediaAdapter(Context context, boolean expandable, boolean requery)
|
public SongMediaAdapter(Context context, boolean expandable, boolean requery)
|
||||||
{
|
{
|
||||||
super(context,
|
super(context, Song.TYPE_SONG, expandable, requery);
|
||||||
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
|
||||||
new String[] { MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.TITLE },
|
|
||||||
new String[] { MediaStore.Audio.Media.ARTIST_KEY, MediaStore.Audio.Media.ALBUM_KEY, MediaStore.Audio.Media.TITLE_KEY },
|
|
||||||
expandable, requery);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,6 +90,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
mTabHost.addTab(mTabHost.newTabSpec("tab_artists").setIndicator(res.getText(R.string.artists), res.getDrawable(R.drawable.tab_artists)).setContent(R.id.artist_list));
|
mTabHost.addTab(mTabHost.newTabSpec("tab_artists").setIndicator(res.getText(R.string.artists), res.getDrawable(R.drawable.tab_artists)).setContent(R.id.artist_list));
|
||||||
mTabHost.addTab(mTabHost.newTabSpec("tab_albums").setIndicator(res.getText(R.string.albums), res.getDrawable(R.drawable.tab_albums)).setContent(R.id.album_list));
|
mTabHost.addTab(mTabHost.newTabSpec("tab_albums").setIndicator(res.getText(R.string.albums), res.getDrawable(R.drawable.tab_albums)).setContent(R.id.album_list));
|
||||||
mTabHost.addTab(mTabHost.newTabSpec("tab_songs").setIndicator(res.getText(R.string.songs), res.getDrawable(R.drawable.tab_songs)).setContent(R.id.song_list));
|
mTabHost.addTab(mTabHost.newTabSpec("tab_songs").setIndicator(res.getText(R.string.songs), res.getDrawable(R.drawable.tab_songs)).setContent(R.id.song_list));
|
||||||
|
mTabHost.addTab(mTabHost.newTabSpec("tab_playlists").setIndicator(res.getText(R.string.playlists), res.getDrawable(R.drawable.tab_playlists)).setContent(R.id.playlist_list));
|
||||||
|
|
||||||
mSearchBox = findViewById(R.id.search_box);
|
mSearchBox = findViewById(R.id.search_box);
|
||||||
|
|
||||||
@ -189,11 +190,10 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
long id = view.getMediaId();
|
long id = view.getMediaId();
|
||||||
int field = view.getFieldCount();
|
|
||||||
|
|
||||||
Intent intent = new Intent(this, PlaybackService.class);
|
Intent intent = new Intent(this, PlaybackService.class);
|
||||||
intent.setAction(action);
|
intent.setAction(action);
|
||||||
intent.putExtra("type", field);
|
intent.putExtra("type", view.getMediaType());
|
||||||
intent.putExtra("id", id);
|
intent.putExtra("id", id);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
|
|
||||||
@ -413,9 +413,10 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
{
|
{
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case MSG_INIT:
|
case MSG_INIT:
|
||||||
setupView(R.id.artist_list, new MediaAdapter(this, MediaAdapter.TYPE_ARTIST, true, false));
|
setupView(R.id.artist_list, new MediaAdapter(this, Song.TYPE_ARTIST, true, false));
|
||||||
setupView(R.id.album_list, new MediaAdapter(this, MediaAdapter.TYPE_ALBUM, true, false));
|
setupView(R.id.album_list, new MediaAdapter(this, Song.TYPE_ALBUM, true, false));
|
||||||
setupView(R.id.song_list, new SongMediaAdapter(this, false, false));
|
setupView(R.id.song_list, new SongMediaAdapter(this, false, false));
|
||||||
|
setupView(R.id.playlist_list, new MediaAdapter(this, Song.TYPE_PLAYLIST, false, true));
|
||||||
|
|
||||||
ContentResolver resolver = getContentResolver();
|
ContentResolver resolver = getContentResolver();
|
||||||
Observer observer = new Observer(mHandler);
|
Observer observer = new Observer(mHandler);
|
||||||
@ -440,7 +441,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
for (int i = 0; i != 3; ++i)
|
for (int i = 0; i != 4; ++i)
|
||||||
getAdapter(i).requery();
|
getAdapter(i).requery();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -352,8 +352,10 @@ public final class SongTimeline {
|
|||||||
* will be ordered by album and then by track number.
|
* will be ordered by album and then by track number.
|
||||||
*
|
*
|
||||||
* @param enqueue If true, enqueue the set. If false, play the set.
|
* @param enqueue If true, enqueue the set. If false, play the set.
|
||||||
* @param type 1, 2, or 3, indicating artist, album, or song, respectively.
|
* @param type The type represented by the id. Must be one of the
|
||||||
* @param id The MediaStore id of the artist, album, or song.
|
* Song.FIELD_* constants.
|
||||||
|
* @param id The id of the element in the MediaStore content provider for
|
||||||
|
* the given type.
|
||||||
*/
|
*/
|
||||||
public void chooseSongs(boolean enqueue, int type, long id)
|
public void chooseSongs(boolean enqueue, int type, long id)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user