Add a play all row
This commit is contained in:
parent
690789273b
commit
f524be7199
@ -93,6 +93,9 @@ THE SOFTWARE.
|
||||
<string name="none">None</string>
|
||||
<string name="unknown">Unknown</string>
|
||||
<string name="title_by_artist">%1$s by %2$s</string>
|
||||
<string name="play_all">Play All</string>
|
||||
<string name="enqueue_all">Enqueue All</string>
|
||||
<string name="all_songs">All Songs</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<plurals name="seconds">
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
@ -90,6 +89,15 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
* The section indexer, for the letter pop-up when scrolling.
|
||||
*/
|
||||
private MusicAlphabetIndexer mIndexer;
|
||||
/**
|
||||
* True if this adapter should have a special MediaView with custom text in
|
||||
* the first row.
|
||||
*/
|
||||
private boolean mHasHeader;
|
||||
/**
|
||||
* The text to show in the header.
|
||||
*/
|
||||
private String mHeaderText;
|
||||
|
||||
/**
|
||||
* Construct a MediaAdapter representing the given <code>type</code> of
|
||||
@ -101,15 +109,17 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
* 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 hasHeader Wether this view has a header row.
|
||||
* @param limiter An initial limiter to use
|
||||
*/
|
||||
public MediaAdapter(SongSelector activity, int type, boolean expandable, Limiter limiter)
|
||||
public MediaAdapter(SongSelector activity, int type, boolean expandable, boolean hasHeader, Limiter limiter)
|
||||
{
|
||||
super(activity, null, false);
|
||||
|
||||
mActivity = activity;
|
||||
mType = type;
|
||||
mExpandable = expandable;
|
||||
mHasHeader = hasHeader;
|
||||
mLimiter = limiter;
|
||||
mIndexer = new MusicAlphabetIndexer(1);
|
||||
|
||||
@ -145,6 +155,75 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
int count = super.getCount();
|
||||
if (count == 0)
|
||||
return 0;
|
||||
else if (mHasHeader)
|
||||
return count + 1;
|
||||
else
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int pos)
|
||||
{
|
||||
if (mHasHeader) {
|
||||
if (pos == 0)
|
||||
return null;
|
||||
else
|
||||
pos -= 1;
|
||||
}
|
||||
|
||||
return super.getItem(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int pos)
|
||||
{
|
||||
if (mHasHeader) {
|
||||
if (pos == 0)
|
||||
return -1;
|
||||
else
|
||||
pos -= 1;
|
||||
}
|
||||
|
||||
return super.getItemId(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int pos, View convertView, ViewGroup parent)
|
||||
{
|
||||
if (mHasHeader) {
|
||||
if (pos == 0) {
|
||||
MediaView view;
|
||||
if (convertView == null)
|
||||
view = new MediaView(mActivity, mExpandable);
|
||||
else
|
||||
view = (MediaView)convertView;
|
||||
view.makeHeader(mHeaderText);
|
||||
return view;
|
||||
} else {
|
||||
pos -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return super.getView(pos, convertView, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the header text to be shown in the first row.
|
||||
*
|
||||
* @param text The new text.
|
||||
*/
|
||||
public void setHeaderText(String text)
|
||||
{
|
||||
mHeaderText = text;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform filtering on a background thread.
|
||||
*
|
||||
@ -159,14 +238,13 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the backing content provider. Should be called on a background
|
||||
* thread.
|
||||
* Build the query to be run with runQuery().
|
||||
*
|
||||
* @param forceMusicCheck Force the is_music check to be added to the
|
||||
* selection.
|
||||
*/
|
||||
public void runQuery()
|
||||
public QueryTask buildQuery(boolean forceMusicCheck)
|
||||
{
|
||||
ContentResolver resolver = mActivity.getContentResolver();
|
||||
Cursor cursor;
|
||||
|
||||
String constraint = mConstraint;
|
||||
Limiter limiter = mLimiter;
|
||||
|
||||
@ -187,7 +265,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
else
|
||||
sort = mFieldKeys[mFieldKeys.length - 1];
|
||||
|
||||
if (mType == MediaUtils.TYPE_SONG)
|
||||
if (mType == MediaUtils.TYPE_SONG || forceMusicCheck)
|
||||
selection.append("is_music!=0");
|
||||
|
||||
if (constraint != null && constraint.length() != 0) {
|
||||
@ -228,8 +306,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
if (limiter != null && limiter.type == MediaUtils.TYPE_GENRE) {
|
||||
// Genre is not standard metadata for MediaStore.Audio.Media.
|
||||
// We have to query it through a separate provider. : /
|
||||
QueryTask query = MediaUtils.buildGenreQuery(mLimiter.id, projection, selection.toString(), selectionArgs);
|
||||
cursor = query.runQuery(resolver);
|
||||
return MediaUtils.buildGenreQuery(mLimiter.id, projection, selection.toString(), selectionArgs);
|
||||
} else {
|
||||
if (limiter != null) {
|
||||
if (selection.length() != 0)
|
||||
@ -237,10 +314,8 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
selection.append(mLimiter.selection);
|
||||
}
|
||||
|
||||
cursor = resolver.query(mStore, projection, selection.toString(), selectionArgs, sort);
|
||||
return new QueryTask(mStore, projection, selection.toString(), selectionArgs, sort);
|
||||
}
|
||||
|
||||
mActivity.changeCursor(this, cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -257,7 +332,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
* displayed media to only those that are children of a given parent
|
||||
* media item.
|
||||
*
|
||||
* @param limiter The limiter, created by MediaView.getLimiter()
|
||||
* @param limiter The limiter, created by {@link MediaAdapter#getLimiter(long)}.
|
||||
*/
|
||||
public final void setLimiter(Limiter limiter)
|
||||
{
|
||||
@ -277,31 +352,39 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
/**
|
||||
* Builds a limiter based off of the media represented by the given row.
|
||||
*
|
||||
* @param view The row to create the limiter from.
|
||||
* @param id The id of the row.
|
||||
* @see MediaAdapter#getLimiter()
|
||||
* @see MediaAdapter#setLimiter(MediaAdapter.Limiter)
|
||||
*/
|
||||
public Limiter getLimiter(MediaView view)
|
||||
public Limiter getLimiter(long id)
|
||||
{
|
||||
long id = view.getMediaId();
|
||||
String[] fields;
|
||||
String selection = null;
|
||||
|
||||
Cursor cursor = getCursor();
|
||||
if (cursor == null)
|
||||
return null;
|
||||
for (int i = 0, count = cursor.getCount(); i != count; ++i) {
|
||||
cursor.moveToPosition(i);
|
||||
if (cursor.getLong(0) == id)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mType) {
|
||||
case MediaUtils.TYPE_ARTIST: {
|
||||
fields = new String[] { view.getTitle() };
|
||||
fields = new String[] { cursor.getString(1) };
|
||||
String field = MediaStore.Audio.Media.ARTIST_ID;
|
||||
selection = String.format("%s=%d", field, id);
|
||||
break;
|
||||
}
|
||||
case MediaUtils.TYPE_ALBUM: {
|
||||
fields = new String[] { view.getSubTitle(), view.getTitle() };
|
||||
fields = new String[] { cursor.getString(2), cursor.getString(1) };
|
||||
String field = MediaStore.Audio.Media.ALBUM_ID;
|
||||
selection = String.format("%s=%d", field, id);
|
||||
break;
|
||||
}
|
||||
case MediaUtils.TYPE_GENRE:
|
||||
fields = new String[] { view.getTitle() };
|
||||
fields = new String[] { cursor.getString(1) };
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("getLimiter() is not supported for media type: " + mType);
|
||||
@ -326,7 +409,13 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
@Override
|
||||
public int getPositionForSection(int section)
|
||||
{
|
||||
return mIndexer.getPositionForSection(section);
|
||||
int offset = 0;
|
||||
if (mHasHeader) {
|
||||
if (section == 0)
|
||||
return 0;
|
||||
offset = 1;
|
||||
}
|
||||
return offset + mIndexer.getPositionForSection(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -351,7 +440,7 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer {
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent)
|
||||
{
|
||||
return new MediaView(context, this, mExpandable);
|
||||
return new MediaView(context, mExpandable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,41 +187,6 @@ public class MediaUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array containing all the song ids that match the specified parameters. Should be run on a background thread.
|
||||
*
|
||||
* @param context A context to use.
|
||||
* @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(Context context, int type, long id)
|
||||
{
|
||||
if (type == TYPE_SONG)
|
||||
return new long[] { id };
|
||||
|
||||
String[] projection = type == MediaUtils.TYPE_PLAYLIST ?
|
||||
Song.EMPTY_PLAYLIST_PROJECTION : Song.EMPTY_PROJECTION;
|
||||
Cursor cursor = buildQuery(type, id, projection, null).runQuery(context.getContentResolver());
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
int count = cursor.getCount();
|
||||
if (count == 0)
|
||||
return null;
|
||||
|
||||
long[] songs = new long[count];
|
||||
for (int i = 0; i != count; ++i) {
|
||||
if (!cursor.moveToNext())
|
||||
return null;
|
||||
songs[i] = cursor.getLong(0);
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return songs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the songs in the given media set. Should be run on a
|
||||
* background thread.
|
||||
|
@ -76,10 +76,6 @@ public final class MediaView extends View {
|
||||
sPaint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The MediaAdapter that owns this view.
|
||||
*/
|
||||
private MediaAdapter mOwner;
|
||||
/**
|
||||
* The MediaStore id of the media represented by this view.
|
||||
*/
|
||||
@ -104,19 +100,21 @@ public final class MediaView extends View {
|
||||
* The cached measured view height.
|
||||
*/
|
||||
private int mViewHeight;
|
||||
/**
|
||||
* True if this view is a header. Will override expandable setting to false.
|
||||
*/
|
||||
private boolean mIsHeader;
|
||||
|
||||
/**
|
||||
* Construct a MediaView.
|
||||
*
|
||||
* @param context A Context to use.
|
||||
* @param owner The MediaAdapter that owns this view.
|
||||
* @param expandable True if the expander should be shown.
|
||||
*/
|
||||
public MediaView(Context context, MediaAdapter owner, boolean expandable)
|
||||
public MediaView(Context context, boolean expandable)
|
||||
{
|
||||
super(context);
|
||||
|
||||
mOwner = owner;
|
||||
mExpandable = expandable;
|
||||
|
||||
mViewHeight = (int)(7 * sTextSize / 2);
|
||||
@ -148,7 +146,7 @@ public final class MediaView extends View {
|
||||
|
||||
Paint paint = sPaint;
|
||||
|
||||
if (mExpandable) {
|
||||
if (mExpandable && !mIsHeader) {
|
||||
Bitmap expander = sExpander;
|
||||
width -= padding * 4 + expander.getWidth();
|
||||
|
||||
@ -188,24 +186,6 @@ public final class MediaView extends View {
|
||||
paint.setShader(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MediaAdapter that owns this view.
|
||||
*/
|
||||
public MediaAdapter getOwner()
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of media this view represents.
|
||||
*
|
||||
* @return One of MediaUtils.TYPE_*.
|
||||
*/
|
||||
public int getMediaType()
|
||||
{
|
||||
return mOwner.getMediaType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MediaStore id of the media represented by this view.
|
||||
*/
|
||||
@ -222,14 +202,6 @@ public final class MediaView extends View {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secondary text in the view, displayed on the lower line.
|
||||
*/
|
||||
public String getSubTitle()
|
||||
{
|
||||
return mSubTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the expander arrow was pressed in the last touch
|
||||
* event.
|
||||
@ -247,6 +219,18 @@ public final class MediaView extends View {
|
||||
return mExpandable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this view to be a header (custom text, never expandable).
|
||||
*
|
||||
* @param text The text to show.
|
||||
*/
|
||||
public void makeHeader(String text)
|
||||
{
|
||||
mIsHeader = true;
|
||||
mTitle = text;
|
||||
mSubTitle = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the fields in this view with the data from the given Cursor.
|
||||
*
|
||||
@ -258,6 +242,7 @@ public final class MediaView extends View {
|
||||
*/
|
||||
public void updateMedia(Cursor cursor, boolean useSecondary)
|
||||
{
|
||||
mIsHeader = false;
|
||||
mId = cursor.getLong(0);
|
||||
mTitle = cursor.getString(1);
|
||||
if (useSecondary)
|
||||
@ -265,13 +250,21 @@ public final class MediaView extends View {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the view is set to be a "Play/Enqueue All" header.
|
||||
*/
|
||||
public boolean isHeader()
|
||||
{
|
||||
return mIsHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update mExpanderPressed.
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
if (mExpandable)
|
||||
if (mExpandable && !mIsHeader)
|
||||
mExpanderPressed = event.getX() > getWidth() - sExpander.getWidth() - 2 * sTextSize;
|
||||
return false;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ package org.kreed.vanilla;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
@ -60,6 +61,10 @@ public class NewPlaylistDialog extends Dialog implements TextWatcher, View.OnCli
|
||||
* action (e.g. "Create" or "Rename").
|
||||
*/
|
||||
private int mActionRes;
|
||||
/**
|
||||
* An intent that is simply stored in the dialog.
|
||||
*/
|
||||
private Intent mIntent;
|
||||
|
||||
/**
|
||||
* Create a NewPlaylistDialog.
|
||||
@ -69,12 +74,14 @@ public class NewPlaylistDialog extends Dialog implements TextWatcher, View.OnCli
|
||||
* disabled when the EditText contains this text.
|
||||
* @param actionText A string resource describing the default positive
|
||||
* action (e.g. "Create").
|
||||
* @param intent An optional intent to store with the dialog.
|
||||
*/
|
||||
public NewPlaylistDialog(Context context, String initialText, int actionText)
|
||||
public NewPlaylistDialog(Context context, String initialText, int actionText, Intent intent)
|
||||
{
|
||||
super(context);
|
||||
mInitialText = initialText;
|
||||
mActionRes = actionText;
|
||||
mIntent = intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -106,6 +113,14 @@ public class NewPlaylistDialog extends Dialog implements TextWatcher, View.OnCli
|
||||
return mText.getText().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stored intent.
|
||||
*/
|
||||
public Intent getIntent()
|
||||
{
|
||||
return mIntent;
|
||||
}
|
||||
|
||||
public void afterTextChanged(Editable s)
|
||||
{
|
||||
// do nothing
|
||||
|
@ -142,17 +142,23 @@ public class Playlist {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given set of song ids to the playlist with the given id.
|
||||
* Run the given query and add the results to the given playlist. Should be
|
||||
* run on a background thread.
|
||||
*
|
||||
* @param context A context to use.
|
||||
* @param playlistId The MediaStore.Audio.Playlist id of the playlist to
|
||||
* modify.
|
||||
* @param toAdd The MediaStore ids of all the songs to be added to the
|
||||
* playlist.
|
||||
* @param query The query to run. The audio id should be the first column.
|
||||
* @return The number of songs that were added to the playlist.
|
||||
*/
|
||||
public static void addToPlaylist(Context context, long playlistId, long[] toAdd)
|
||||
public static int addToPlaylist(Context context, long playlistId, QueryTask query)
|
||||
{
|
||||
if (playlistId == -1)
|
||||
return 0;
|
||||
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
|
||||
// Find the greatest PLAY_ORDER in the playlist
|
||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
||||
String[] projection = new String[] { MediaStore.Audio.Playlists.Members.PLAY_ORDER };
|
||||
Cursor cursor = resolver.query(uri, projection, null, null, null);
|
||||
@ -161,13 +167,25 @@ public class Playlist {
|
||||
base = cursor.getInt(0) + 1;
|
||||
cursor.close();
|
||||
|
||||
ContentValues[] values = new ContentValues[toAdd.length];
|
||||
for (int i = 0; i != values.length; ++i) {
|
||||
values[i] = new ContentValues(1);
|
||||
values[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + i));
|
||||
values[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, toAdd[i]);
|
||||
Cursor from = query.runQuery(resolver);
|
||||
if (from == null)
|
||||
return 0;
|
||||
|
||||
int count = from.getCount();
|
||||
if (count > 0) {
|
||||
ContentValues[] values = new ContentValues[count];
|
||||
for (int i = 0; i != count; ++i) {
|
||||
from.moveToPosition(i);
|
||||
values[i] = new ContentValues(1);
|
||||
values[i].put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + i));
|
||||
values[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, from.getLong(0));
|
||||
}
|
||||
resolver.bulkInsert(uri, values);
|
||||
}
|
||||
resolver.bulkInsert(uri, values);
|
||||
|
||||
from.close();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,6 +49,26 @@ public class QueryTask {
|
||||
mSortOrder = sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the uri of the pending query.
|
||||
*
|
||||
* @param uri The new uri.
|
||||
*/
|
||||
public void setUri(Uri uri)
|
||||
{
|
||||
mUri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the projection of the pending query.
|
||||
*
|
||||
* @param projection The new projection.
|
||||
*/
|
||||
public void setProjection(String[] projection)
|
||||
{
|
||||
mProjection = projection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the query. Should be called on a background thread.
|
||||
*
|
||||
|
@ -151,11 +151,11 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
|
||||
mLimiterViews = (ViewGroup)findViewById(R.id.limiter_layout);
|
||||
|
||||
mArtistAdapter = setupView(R.id.artist_list, MediaUtils.TYPE_ARTIST, true, null);
|
||||
mAlbumAdapter = setupView(R.id.album_list, MediaUtils.TYPE_ALBUM, true, state == null ? null : (MediaAdapter.Limiter)state.getSerializable("limiter_albums"));
|
||||
mSongAdapter = setupView(R.id.song_list, MediaUtils.TYPE_SONG, false, state == null ? null : (MediaAdapter.Limiter)state.getSerializable("limiter_songs"));
|
||||
mPlaylistAdapter = setupView(R.id.playlist_list, MediaUtils.TYPE_PLAYLIST, false, null);
|
||||
mGenreAdapter = setupView(R.id.genre_list, MediaUtils.TYPE_GENRE, true, state == null ? null : (MediaAdapter.Limiter)state.getSerializable("limiter_genres"));
|
||||
mArtistAdapter = setupView(R.id.artist_list, MediaUtils.TYPE_ARTIST, true, true, null);
|
||||
mAlbumAdapter = setupView(R.id.album_list, MediaUtils.TYPE_ALBUM, true, true, state == null ? null : (MediaAdapter.Limiter)state.getSerializable("limiter_albums"));
|
||||
mSongAdapter = setupView(R.id.song_list, MediaUtils.TYPE_SONG, false, true, state == null ? null : (MediaAdapter.Limiter)state.getSerializable("limiter_songs"));
|
||||
mPlaylistAdapter = setupView(R.id.playlist_list, MediaUtils.TYPE_PLAYLIST, false, false, null);
|
||||
mGenreAdapter = setupView(R.id.genre_list, MediaUtils.TYPE_GENRE, true, false, state == null ? null : (MediaAdapter.Limiter)state.getSerializable("limiter_genres"));
|
||||
// These should be in the same order as MediaUtils.TYPE_*
|
||||
mAdapters = new MediaAdapter[] { mArtistAdapter, mAlbumAdapter, mSongAdapter, mPlaylistAdapter, mGenreAdapter };
|
||||
|
||||
@ -185,7 +185,8 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
mDefaultAction = Integer.parseInt(settings.getString("default_action_int", "0"));
|
||||
mLastActedId = 0;
|
||||
mLastActedId = -2;
|
||||
updateHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -239,37 +240,58 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds songs matching the type and id of the given view to the song timelime.
|
||||
*
|
||||
* @param view The MediaView to get type/id data from
|
||||
* @param action One of SongSelector.ACTION_*
|
||||
* Update the first row of the lists with the appropriate action (play all
|
||||
* or enqueue all).
|
||||
*/
|
||||
private void pickSongs(MediaView view, int action)
|
||||
private void updateHeaders()
|
||||
{
|
||||
int type = view.getMediaType();
|
||||
long id = view.getMediaId();
|
||||
|
||||
int action = mDefaultAction;
|
||||
if (action == ACTION_LAST_USED)
|
||||
action = mLastAction;
|
||||
else
|
||||
mLastAction = action;
|
||||
|
||||
int mode = modeForAction[action];
|
||||
String[] projection = type == MediaUtils.TYPE_PLAYLIST ?
|
||||
Song.FILLED_PLAYLIST_PROJECTION : Song.FILLED_PROJECTION;
|
||||
QueryTask query = MediaUtils.buildQuery(type, id, projection, null);
|
||||
PlaybackService.get(this).addSongs(mode, query);
|
||||
int res = action == ACTION_ENQUEUE ? R.string.enqueue_all : R.string.play_all;
|
||||
String text = getString(res);
|
||||
mArtistAdapter.setHeaderText(text);
|
||||
mAlbumAdapter.setHeaderText(text);
|
||||
mSongAdapter.setHeaderText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* "Expand" the view by setting the limiter from the given view and
|
||||
* switching to the appropriate tab.
|
||||
* Adds songs matching the data from the given intent to the song timelime.
|
||||
*
|
||||
* @param view The view to expand from.
|
||||
* @param intent An intent created with
|
||||
* {@link SongSelector#createClickIntent(MediaAdapter,MediaView)}.
|
||||
* @param action One of SongSelector.ACTION_*
|
||||
*/
|
||||
private void expand(MediaView view)
|
||||
private void pickSongs(Intent intent, int action)
|
||||
{
|
||||
mTabHost.setCurrentTab(setLimiter(view.getOwner().getLimiter(view)));
|
||||
if (action == ACTION_LAST_USED)
|
||||
action = mLastAction;
|
||||
|
||||
int mode = modeForAction[action];
|
||||
QueryTask query = buildQueryFromIntent(intent, false);
|
||||
PlaybackService.get(this).addSongs(mode, query);
|
||||
|
||||
mLastActedId = intent.getLongExtra("id", -1);
|
||||
|
||||
if (mDefaultAction == ACTION_LAST_USED && mLastAction != action) {
|
||||
mLastAction = action;
|
||||
updateHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Expand" the view represented by the given intent by setting the limiter
|
||||
* from the view and switching to the appropriate tab.
|
||||
*
|
||||
* @param intent An intent created with
|
||||
* {@link SongSelector#createClickIntent(MediaAdapter,MediaView)}.
|
||||
*/
|
||||
private void expand(Intent intent)
|
||||
{
|
||||
int type = intent.getIntExtra("type", 1);
|
||||
long id = intent.getLongExtra("id", -1);
|
||||
mTabHost.setCurrentTab(setLimiter(mAdapters[type - 1].getLimiter(id)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,11 +333,11 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
{
|
||||
MediaView mediaView = (MediaView)view;
|
||||
if (mediaView.isExpanderPressed())
|
||||
expand(mediaView);
|
||||
expand(createClickIntent((MediaAdapter)list.getAdapter(), mediaView));
|
||||
else if (id == mLastActedId)
|
||||
startActivity(new Intent(this, FullPlaybackActivity.class));
|
||||
else
|
||||
pickSongs(mediaView, mDefaultAction);
|
||||
pickSongs(createClickIntent((MediaAdapter)list.getAdapter(), mediaView), mDefaultAction);
|
||||
}
|
||||
|
||||
public void afterTextChanged(Editable editable)
|
||||
@ -407,8 +429,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
Cursor cursor = resolver.query(uri, projection, limiter.selection, null, null);
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToNext()) {
|
||||
limiter = new MediaAdapter.Limiter(cursor.getLong(0), MediaUtils.TYPE_ARTIST, MediaStore.Audio.Media.ARTIST_ID, new String[] { limiter.names[0] });
|
||||
setLimiter(limiter);
|
||||
setLimiter(mArtistAdapter.getLimiter(cursor.getLong(0)));
|
||||
updateLimiterViews();
|
||||
cursor.close();
|
||||
return;
|
||||
@ -424,6 +445,54 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an intent based off of the media represented by the given view.
|
||||
*
|
||||
* @param adapter The adapter that owns the view.
|
||||
* @param view The MediaView to build from.
|
||||
*/
|
||||
private static Intent createClickIntent(MediaAdapter adapter, MediaView view)
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("type", adapter.getMediaType());
|
||||
intent.putExtra("id", view.getMediaId());
|
||||
intent.putExtra("isHeader", view.isHeader());
|
||||
intent.putExtra("title", view.getTitle());
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a media query based off the data stored in the given intent.
|
||||
*
|
||||
* @param intent An intent created with
|
||||
* {@link SongSelector#createClickIntent(MediaAdapter,MediaView)}.
|
||||
* @param empty If true, use the empty projection (only query id).
|
||||
*/
|
||||
private QueryTask buildQueryFromIntent(Intent intent, boolean empty)
|
||||
{
|
||||
int type = intent.getIntExtra("type", 1);
|
||||
|
||||
String[] projection;
|
||||
if (type == MediaUtils.TYPE_PLAYLIST)
|
||||
projection = empty ? Song.EMPTY_PLAYLIST_PROJECTION : Song.FILLED_PLAYLIST_PROJECTION;
|
||||
else
|
||||
projection = empty ? Song.EMPTY_PROJECTION : Song.FILLED_PROJECTION;
|
||||
|
||||
QueryTask query;
|
||||
if (intent.getBooleanExtra("isHeader", false)) {
|
||||
query = mAdapters[type - 1].buildQuery(true);
|
||||
query.setProjection(projection);
|
||||
// we want to query songs, not albums or artists
|
||||
if (type != MediaUtils.TYPE_SONG)
|
||||
query.setUri(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
|
||||
} else {
|
||||
long id = intent.getLongExtra("id", -1);
|
||||
query = MediaUtils.buildQuery(type, id, projection, null);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
private static final int MENU_PLAY = 0;
|
||||
private static final int MENU_ENQUEUE = 1;
|
||||
private static final int MENU_EXPAND = 2;
|
||||
@ -432,70 +501,68 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
private static final int MENU_DELETE = 5;
|
||||
private static final int MENU_EDIT = 6;
|
||||
private static final int MENU_RENAME_PLAYLIST = 7;
|
||||
private static final int MENU_SELECT_PLAYLIST = 8;
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View listView, ContextMenu.ContextMenuInfo absInfo)
|
||||
{
|
||||
MediaAdapter adapter = (MediaAdapter)((ListView)listView).getAdapter();
|
||||
MediaView view = (MediaView)((AdapterView.AdapterContextMenuInfo)absInfo).targetView;
|
||||
int type = view.getMediaType();
|
||||
int id = (int)view.getMediaId();
|
||||
|
||||
menu.setHeaderTitle(view.getTitle());
|
||||
menu.add(0, MENU_PLAY, 0, R.string.play);
|
||||
menu.add(0, MENU_ENQUEUE, 0, R.string.enqueue);
|
||||
if (view.getMediaType() == MediaUtils.TYPE_PLAYLIST) {
|
||||
menu.add(0, MENU_RENAME_PLAYLIST, 0, R.string.rename);
|
||||
menu.add(0, MENU_EDIT, 0, R.string.edit);
|
||||
// Store view data in intent to avoid problems when the view data changes
|
||||
// as worked is performed in the background.
|
||||
Intent intent = createClickIntent(adapter, view);
|
||||
|
||||
if (view.isHeader())
|
||||
menu.setHeaderTitle(getString(R.string.all_songs));
|
||||
else
|
||||
menu.setHeaderTitle(view.getTitle());
|
||||
|
||||
menu.add(0, MENU_PLAY, 0, R.string.play).setIntent(intent);
|
||||
menu.add(0, MENU_ENQUEUE, 0, R.string.enqueue).setIntent(intent);
|
||||
if (adapter == mPlaylistAdapter) {
|
||||
menu.add(0, MENU_RENAME_PLAYLIST, 0, R.string.rename).setIntent(intent);
|
||||
menu.add(0, MENU_EDIT, 0, R.string.edit).setIntent(intent);
|
||||
}
|
||||
SubMenu playlistMenu = menu.addSubMenu(0, MENU_ADD_TO_PLAYLIST, 0, R.string.add_to_playlist);
|
||||
menu.addSubMenu(0, MENU_ADD_TO_PLAYLIST, 0, R.string.add_to_playlist).getItem().setIntent(intent);
|
||||
if (view.hasExpanders())
|
||||
menu.add(0, MENU_EXPAND, 0, R.string.expand);
|
||||
menu.add(0, MENU_DELETE, 0, R.string.delete);
|
||||
|
||||
playlistMenu.add(type, MENU_NEW_PLAYLIST, id, R.string.new_playlist);
|
||||
Playlist[] playlists = Playlist.getPlaylists(this);
|
||||
if (playlists != null) {
|
||||
for (int i = 0; i != playlists.length; ++i)
|
||||
playlistMenu.add(type, (int)playlists[i].id + 100, id, playlists[i].name);
|
||||
}
|
||||
menu.add(0, MENU_EXPAND, 0, R.string.expand).setIntent(intent);
|
||||
if (!view.isHeader())
|
||||
menu.add(0, MENU_DELETE, 0, R.string.delete).setIntent(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of songs to a playlists. Sets can be all songs from an artist,
|
||||
* album, playlist, or a single song. Displays a Toast notifying of
|
||||
* success.
|
||||
* Add a set of songs represented by the intent to a playlist. Displays a
|
||||
* Toast notifying of success.
|
||||
*
|
||||
* @param playlistId The MediaStore.Audio.Playlists id of the playlist to
|
||||
* be modified.
|
||||
* @param type The type of media the mediaId represents; one of the
|
||||
* Song.TYPE_* constants.
|
||||
* @param mediaId The MediaStore id of the element to be added.
|
||||
* @param title The title of the playlist being added to (used for the
|
||||
* Toast).
|
||||
* @param playlistId The id of the playlist to add to.
|
||||
* @param intent An intent created with
|
||||
* {@link SongSelector#createClickIntent(MediaAdapter,MediaView)}.
|
||||
*/
|
||||
private void addToPlaylist(long playlistId, int type, long mediaId, CharSequence title)
|
||||
private void addToPlaylist(long playlistId, Intent intent)
|
||||
{
|
||||
long[] ids = MediaUtils.getAllSongIdsWith(this, type, mediaId);
|
||||
Playlist.addToPlaylist(this, playlistId, ids);
|
||||
QueryTask query = buildQueryFromIntent(intent, true);
|
||||
int count = Playlist.addToPlaylist(this, playlistId, query);
|
||||
|
||||
String message = getResources().getQuantityString(R.plurals.added_to_playlist, ids.length, ids.length, title);
|
||||
String message = getResources().getQuantityString(R.plurals.added_to_playlist, count, count, intent.getStringExtra("playlistName"));
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the media with the specified type and id and show a Toast
|
||||
* Delete the media represented by the given intent and show a Toast
|
||||
* informing the user of this.
|
||||
*
|
||||
* @param type The type of media; one of the MediaUtils.TYPE_* constants.
|
||||
* @param id The MediaStore id of the media.
|
||||
* @param title The title of the playlist, to be displayed in the Toast.
|
||||
* Only used when deleting a playlist.
|
||||
* @param intent An intent created with
|
||||
* {@link SongSelector#createClickIntent(MediaAdapter,MediaView)}.
|
||||
*/
|
||||
private void delete(int type, long id, String title)
|
||||
private void delete(Intent intent)
|
||||
{
|
||||
int type = intent.getIntExtra("type", 1);
|
||||
long id = intent.getLongExtra("id", -1);
|
||||
|
||||
if (type == MediaUtils.TYPE_PLAYLIST) {
|
||||
Playlist.deletePlaylist(this, id);
|
||||
String message = getResources().getString(R.string.playlist_deleted, title);
|
||||
String message = getResources().getString(R.string.playlist_deleted, intent.getStringExtra("title"));
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
int count = MediaUtils.deleteMedia(this, type, id);
|
||||
@ -507,58 +574,57 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item)
|
||||
{
|
||||
int id = item.getItemId();
|
||||
int type = item.getGroupId();
|
||||
int mediaId = item.getOrder();
|
||||
Intent intent = item.getIntent();
|
||||
|
||||
switch (id) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_EXPAND:
|
||||
expand((MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView);
|
||||
expand(intent);
|
||||
break;
|
||||
case MENU_ENQUEUE:
|
||||
pickSongs((MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView, ACTION_ENQUEUE);
|
||||
pickSongs(intent, ACTION_ENQUEUE);
|
||||
break;
|
||||
case MENU_PLAY:
|
||||
pickSongs((MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView, ACTION_PLAY);
|
||||
pickSongs(intent, ACTION_PLAY);
|
||||
break;
|
||||
case MENU_NEW_PLAYLIST: {
|
||||
NewPlaylistDialog dialog = new NewPlaylistDialog(this, null, R.string.create);
|
||||
Message message = mHandler.obtainMessage(MSG_NEW_PLAYLIST, type, mediaId);
|
||||
message.obj = dialog;
|
||||
dialog.setDismissMessage(message);
|
||||
NewPlaylistDialog dialog = new NewPlaylistDialog(this, null, R.string.create, intent);
|
||||
dialog.setDismissMessage(mHandler.obtainMessage(MSG_NEW_PLAYLIST, dialog));
|
||||
dialog.show();
|
||||
break;
|
||||
}
|
||||
case MENU_RENAME_PLAYLIST: {
|
||||
MediaView view = (MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView;
|
||||
NewPlaylistDialog dialog = new NewPlaylistDialog(this, view.getTitle(), R.string.rename);
|
||||
Message message = mHandler.obtainMessage(MSG_RENAME_PLAYLIST, view.getMediaType(), (int)view.getMediaId());
|
||||
message.obj = dialog;
|
||||
dialog.setDismissMessage(message);
|
||||
NewPlaylistDialog dialog = new NewPlaylistDialog(this, intent.getStringExtra("title"), R.string.rename, intent);
|
||||
dialog.setDismissMessage(mHandler.obtainMessage(MSG_RENAME_PLAYLIST, dialog));
|
||||
dialog.show();
|
||||
break;
|
||||
}
|
||||
case MENU_DELETE: {
|
||||
MediaView view = (MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView;
|
||||
type = view.getMediaType();
|
||||
if (type != MediaUtils.TYPE_PLAYLIST)
|
||||
Toast.makeText(this, R.string.deleting, Toast.LENGTH_SHORT).show();
|
||||
Message message = mHandler.obtainMessage(MSG_DELETE, type, (int)view.getMediaId());
|
||||
message.obj = view.getTitle();
|
||||
mHandler.sendMessage(message);
|
||||
case MENU_DELETE:
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_DELETE, intent));
|
||||
break;
|
||||
case MENU_ADD_TO_PLAYLIST: {
|
||||
SubMenu playlistMenu = item.getSubMenu();
|
||||
playlistMenu.add(0, MENU_NEW_PLAYLIST, 0, R.string.new_playlist).setIntent(intent);
|
||||
Playlist[] playlists = Playlist.getPlaylists(this);
|
||||
if (playlists != null) {
|
||||
for (int i = 0; i != playlists.length; ++i) {
|
||||
Intent copy = new Intent(intent);
|
||||
copy.putExtra("playlist", playlists[i].id);
|
||||
copy.putExtra("playlistName", playlists[i].name);
|
||||
playlistMenu.add(0, MENU_SELECT_PLAYLIST, 0, playlists[i].name).setIntent(copy);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MENU_EDIT:
|
||||
MediaView view = (MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView;
|
||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
|
||||
intent.putExtra("playlist", String.valueOf(view.getMediaId()));
|
||||
startActivity(intent);
|
||||
case MENU_EDIT: {
|
||||
Intent launch = new Intent(Intent.ACTION_EDIT);
|
||||
launch.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
|
||||
launch.putExtra("playlist", String.valueOf(intent.getLongExtra("id", 0)));
|
||||
startActivity(launch);
|
||||
break;
|
||||
}
|
||||
case MENU_SELECT_PLAYLIST:
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_ADD_TO_PLAYLIST, intent));
|
||||
break;
|
||||
default:
|
||||
if (id > 100)
|
||||
addToPlaylist(id - 100, type, mediaId, item.getTitle());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -593,9 +659,10 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
* @param id The id of the ListView
|
||||
* @param type The media type for the adapter.
|
||||
* @param expandable True if the rows are expandable.
|
||||
* @param hasHeader True if the view should have a header row.
|
||||
* @param limiter The initial limiter to set on the adapter.
|
||||
*/
|
||||
private MediaAdapter setupView(int id, int type, boolean expandable, MediaAdapter.Limiter limiter)
|
||||
private MediaAdapter setupView(int id, int type, boolean expandable, boolean hasHeader, MediaAdapter.Limiter limiter)
|
||||
{
|
||||
ListView view = (ListView)findViewById(id);
|
||||
view.setOnItemClickListener(this);
|
||||
@ -604,32 +671,24 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
view.setDivider(null);
|
||||
view.setFastScrollEnabled(true);
|
||||
|
||||
MediaAdapter adapter = new MediaAdapter(this, type, expandable, limiter);
|
||||
MediaAdapter adapter = new MediaAdapter(this, type, expandable, hasHeader, limiter);
|
||||
view.setAdapter(adapter);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call addToPlaylist with the parameters from the given message. The
|
||||
* message must contain the type and id of the media to be added in
|
||||
* arg1 and arg2, respectively. The obj field must be a NewPlaylistDialog
|
||||
* that the name will be taken from.
|
||||
* Call addToPlaylist with the results from a NewPlaylistDialog stored in
|
||||
* obj.
|
||||
*/
|
||||
private static final int MSG_NEW_PLAYLIST = 11;
|
||||
/**
|
||||
* Delete the songs in the set of media with the specified type and id,
|
||||
* given as arg1 and arg2, respectively. If type is a playlist, the
|
||||
* playlist itself will be deleted, not the songs it contains. The obj
|
||||
* field should contain the playlist name (as a String) if type is a
|
||||
* playlist.
|
||||
* Delete the songs represented by the intent stored in obj.
|
||||
*/
|
||||
private static final int MSG_DELETE = 12;
|
||||
/**
|
||||
* Rename the playlist with the parameters from the given message. The
|
||||
* message must contain the type and id of the media to be added in
|
||||
* arg1 and arg2, respectively. The obj field must be a NewPlaylistDialog
|
||||
* that the name will be taken from.
|
||||
* Call renamePlaylist with the results from a NewPlaylistDialog stored in
|
||||
* obj.
|
||||
*/
|
||||
private static final int MSG_RENAME_PLAYLIST = 13;
|
||||
/**
|
||||
@ -637,32 +696,55 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
* obj will contain the MediaAdapter.
|
||||
*/
|
||||
public static final int MSG_RUN_QUERY = 14;
|
||||
/**
|
||||
* Call addToPlaylist with data from the intent in obj.
|
||||
*/
|
||||
public static final int MSG_ADD_TO_PLAYLIST = 15;
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message message)
|
||||
{
|
||||
switch (message.what) {
|
||||
case MSG_ADD_TO_PLAYLIST: {
|
||||
Intent intent = (Intent)message.obj;
|
||||
addToPlaylist(intent.getLongExtra("playlist", -1), intent);
|
||||
break;
|
||||
}
|
||||
case MSG_NEW_PLAYLIST: {
|
||||
NewPlaylistDialog dialog = (NewPlaylistDialog)message.obj;
|
||||
if (dialog.isAccepted()) {
|
||||
String name = dialog.getText();
|
||||
long playlistId = Playlist.createPlaylist(this, name);
|
||||
addToPlaylist(playlistId, message.arg1, message.arg2, name);
|
||||
Intent intent = dialog.getIntent();
|
||||
intent.putExtra("playlistName", name);
|
||||
addToPlaylist(playlistId, intent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_DELETE:
|
||||
delete(message.arg1, message.arg2, (String)message.obj);
|
||||
delete((Intent)message.obj);
|
||||
break;
|
||||
case MSG_RENAME_PLAYLIST: {
|
||||
NewPlaylistDialog dialog = (NewPlaylistDialog)message.obj;
|
||||
if (dialog.isAccepted())
|
||||
Playlist.renamePlaylist(this, message.arg2, dialog.getText());
|
||||
if (dialog.isAccepted()) {
|
||||
long playlistId = dialog.getIntent().getLongExtra("id", -1);
|
||||
Playlist.renamePlaylist(this, playlistId, dialog.getText());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_RUN_QUERY:
|
||||
((MediaAdapter)message.obj).runQuery();
|
||||
case MSG_RUN_QUERY: {
|
||||
final MediaAdapter adapter = (MediaAdapter)message.obj;
|
||||
QueryTask query = adapter.buildQuery(false);
|
||||
final Cursor cursor = query.runQuery(getContentResolver());
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
adapter.changeCursor(cursor);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return super.handleMessage(message);
|
||||
}
|
||||
@ -681,23 +763,6 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_RUN_QUERY, adapter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given adapter with the given cursor on the UI thread.
|
||||
*
|
||||
* @param adapter The adapter to update.
|
||||
* @param cursor The cursor to update with.
|
||||
*/
|
||||
public void changeCursor(final MediaAdapter adapter, final Cursor cursor)
|
||||
{
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
adapter.changeCursor(cursor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChange()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user