Move bitmap generation and service interaction into a background thread
This commit is contained in:
parent
69ea872f75
commit
88784789ca
@ -29,7 +29,6 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
@ -39,7 +38,7 @@ import android.view.View;
|
|||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
|
|
||||||
public final class CoverView extends View implements Handler.Callback {
|
public final class CoverView extends View {
|
||||||
private static final int STORE_SIZE = 3;
|
private static final int STORE_SIZE = 3;
|
||||||
private static int SNAP_VELOCITY = -1;
|
private static int SNAP_VELOCITY = -1;
|
||||||
|
|
||||||
@ -52,20 +51,27 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
private static Bitmap ALBUM_ICON;
|
private static Bitmap ALBUM_ICON;
|
||||||
private static Bitmap ARTIST_ICON;
|
private static Bitmap ARTIST_ICON;
|
||||||
|
|
||||||
private Scroller mScroller;
|
/**
|
||||||
private Handler mHandler = new Handler(this);
|
* The Handler with which to do background work. Must be initialized by
|
||||||
|
* the containing Activity.
|
||||||
|
*/
|
||||||
|
Handler mHandler;
|
||||||
|
/**
|
||||||
|
* Whether or not to display song info on top of the cover art. Can be
|
||||||
|
* initialized by the containing Activity.
|
||||||
|
*/
|
||||||
|
boolean mSeparateInfo;
|
||||||
|
|
||||||
private Song[] mSongs = new Song[3];
|
private Song[] mSongs = new Song[3];
|
||||||
private Bitmap[] mBitmaps = new Bitmap[3];
|
private Bitmap[] mBitmaps = new Bitmap[3];
|
||||||
private int mTimelinePos;
|
private int mTimelinePos;
|
||||||
|
private Scroller mScroller;
|
||||||
private VelocityTracker mVelocityTracker;
|
private VelocityTracker mVelocityTracker;
|
||||||
private float mLastMotionX;
|
private float mLastMotionX;
|
||||||
private float mStartX;
|
private float mStartX;
|
||||||
private float mStartY;
|
private float mStartY;
|
||||||
private int mTentativeCover = -1;
|
private int mTentativeCover = -1;
|
||||||
|
|
||||||
private boolean mSeparateInfo;
|
|
||||||
|
|
||||||
public CoverView(Context context, AttributeSet attributes)
|
public CoverView(Context context, AttributeSet attributes)
|
||||||
{
|
{
|
||||||
super(context, attributes);
|
super(context, attributes);
|
||||||
@ -105,21 +111,6 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
bitmap.recycle();
|
bitmap.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Song getCurrentSong()
|
|
||||||
{
|
|
||||||
return mSongs[STORE_SIZE / 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSeparateInfo()
|
|
||||||
{
|
|
||||||
return mSeparateInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSeparateInfo(boolean separate)
|
|
||||||
{
|
|
||||||
mSeparateInfo = separate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the service for initial song info.
|
* Query the service for initial song info.
|
||||||
*/
|
*/
|
||||||
@ -377,18 +368,19 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
mBitmaps[i] = createSeparatedBitmap(mSongs[i], getWidth(), getHeight());
|
mBitmaps[i] = createSeparatedBitmap(mSongs[i], getWidth(), getHeight());
|
||||||
else
|
else
|
||||||
mBitmaps[i] = createOverlappingBitmap(mSongs[i], getWidth(), getHeight());
|
mBitmaps[i] = createOverlappingBitmap(mSongs[i], getWidth(), getHeight());
|
||||||
|
postInvalidate();
|
||||||
if (oldBitmap != null)
|
if (oldBitmap != null)
|
||||||
oldBitmap.recycle();
|
oldBitmap.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshSongs()
|
private void refreshSongs()
|
||||||
{
|
{
|
||||||
mHandler.sendEmptyMessage(1);
|
postLoadSong(1, null);
|
||||||
mHandler.sendEmptyMessage(2);
|
postLoadSong(2, null);
|
||||||
mHandler.sendEmptyMessage(0);
|
postLoadSong(0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shiftCover(int delta)
|
public void go(int delta)
|
||||||
{
|
{
|
||||||
int i = delta > 0 ? STORE_SIZE - 1 : 0;
|
int i = delta > 0 ? STORE_SIZE - 1 : 0;
|
||||||
|
|
||||||
@ -397,21 +389,16 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
|
|
||||||
int from = delta > 0 ? 1 : 0;
|
int from = delta > 0 ? 1 : 0;
|
||||||
int to = delta > 0 ? 0 : 1;
|
int to = delta > 0 ? 0 : 1;
|
||||||
|
|
||||||
System.arraycopy(mSongs, from, mSongs, to, STORE_SIZE - 1);
|
System.arraycopy(mSongs, from, mSongs, to, STORE_SIZE - 1);
|
||||||
System.arraycopy(mBitmaps, from, mBitmaps, to, STORE_SIZE - 1);
|
System.arraycopy(mBitmaps, from, mBitmaps, to, STORE_SIZE - 1);
|
||||||
mSongs[i] = null;
|
mSongs[i] = null;
|
||||||
mBitmaps[i] = null;
|
mBitmaps[i] = null;
|
||||||
|
|
||||||
|
postLoadSong(i, null);
|
||||||
|
|
||||||
mTimelinePos += delta;
|
mTimelinePos += delta;
|
||||||
reset();
|
reset();
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
||||||
mHandler.sendEmptyMessage(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void go(int delta)
|
|
||||||
{
|
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(GO, delta, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset()
|
public void reset()
|
||||||
@ -419,7 +406,7 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
if (!mScroller.isFinished())
|
if (!mScroller.isFinished())
|
||||||
mScroller.abortAnimation();
|
mScroller.abortAnimation();
|
||||||
scrollTo(getWidth(), 0);
|
scrollTo(getWidth(), 0);
|
||||||
invalidate();
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void regenerateBitmaps()
|
private void regenerateBitmaps()
|
||||||
@ -545,32 +532,34 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
|
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
} else if (mTentativeCover != -1) {
|
} else if (mTentativeCover != -1) {
|
||||||
shiftCover(mTentativeCover - 1);
|
int delta = mTentativeCover - 1;
|
||||||
mTentativeCover = -1;
|
mTentativeCover = -1;
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(PlaybackActivity.MSG_SET_SONG, delta, 0));
|
||||||
|
go(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int GO = 10;
|
/**
|
||||||
|
* Load a song in the given position. If the song is null, queries the
|
||||||
public boolean handleMessage(Message message)
|
* PlaybackService for the song at that position.
|
||||||
|
*/
|
||||||
|
void loadSong(int i, Song song)
|
||||||
{
|
{
|
||||||
switch (message.what) {
|
mSongs[i] = song == null ? ContextApplication.service.getSong(i - STORE_SIZE / 2) : song;
|
||||||
case GO:
|
createBitmap(i);
|
||||||
shiftCover(message.arg1);
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
int i = message.what;
|
|
||||||
if (message.obj == null)
|
|
||||||
mSongs[i] = ContextApplication.service.getSong(i - STORE_SIZE / 2);
|
|
||||||
else
|
|
||||||
mSongs[i] = (Song)message.obj;
|
|
||||||
createBitmap(i);
|
|
||||||
if (i == STORE_SIZE / 2)
|
|
||||||
reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
/**
|
||||||
|
* Post a Handler message to call loadSong.
|
||||||
|
*/
|
||||||
|
private void postLoadSong(final int i, final Song song)
|
||||||
|
{
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
loadSong(i, song);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -585,7 +574,7 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
if (PlaybackService.EVENT_REPLACE_SONG.equals(action)) {
|
if (PlaybackService.EVENT_REPLACE_SONG.equals(action)) {
|
||||||
int i = STORE_SIZE / 2 + intent.getIntExtra("pos", 0);
|
int i = STORE_SIZE / 2 + intent.getIntExtra("pos", 0);
|
||||||
Song song = intent.getParcelableExtra("song");
|
Song song = intent.getParcelableExtra("song");
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(i, song));
|
postLoadSong(i, song);
|
||||||
} else if (PlaybackService.EVENT_CHANGED.equals(action)) {
|
} else if (PlaybackService.EVENT_CHANGED.equals(action)) {
|
||||||
Song currentSong = mSongs[STORE_SIZE / 2];
|
Song currentSong = mSongs[STORE_SIZE / 2];
|
||||||
Song playingSong = intent.getParcelableExtra("song");
|
Song playingSong = intent.getParcelableExtra("song");
|
||||||
|
@ -24,6 +24,7 @@ import android.content.Intent;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@ -31,7 +32,6 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
@ -42,11 +42,9 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
private View mControlsTop;
|
private View mControlsTop;
|
||||||
private View mControlsBottom;
|
private View mControlsBottom;
|
||||||
|
|
||||||
private ImageView mPlayPauseButton;
|
|
||||||
private SeekBar mSeekBar;
|
private SeekBar mSeekBar;
|
||||||
private TextView mSeekText;
|
private TextView mSeekText;
|
||||||
|
|
||||||
int mState;
|
|
||||||
private int mDuration;
|
private int mDuration;
|
||||||
private boolean mSeekBarTracking;
|
private boolean mSeekBarTracking;
|
||||||
private boolean mPaused;
|
private boolean mPaused;
|
||||||
@ -63,15 +61,16 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
setContentView(R.layout.full_playback);
|
setContentView(R.layout.full_playback);
|
||||||
|
|
||||||
mCoverView = (CoverView)findViewById(R.id.cover_view);
|
mCoverView = (CoverView)findViewById(R.id.cover_view);
|
||||||
|
mCoverView.mHandler = mHandler;
|
||||||
mCoverView.setOnClickListener(this);
|
mCoverView.setOnClickListener(this);
|
||||||
mCoverView.setSeparateInfo(settings.getBoolean("separate_info", false));
|
mCoverView.mSeparateInfo = settings.getBoolean("separate_info", false);
|
||||||
|
|
||||||
mControlsTop = findViewById(R.id.controls_top);
|
mControlsTop = findViewById(R.id.controls_top);
|
||||||
mControlsBottom = findViewById(R.id.controls_bottom);
|
mControlsBottom = findViewById(R.id.controls_bottom);
|
||||||
|
|
||||||
View previousButton = findViewById(R.id.previous);
|
View previousButton = findViewById(R.id.previous);
|
||||||
previousButton.setOnClickListener(this);
|
previousButton.setOnClickListener(this);
|
||||||
mPlayPauseButton = (ImageView)findViewById(R.id.play_pause);
|
mPlayPauseButton = (ControlButton)findViewById(R.id.play_pause);
|
||||||
mPlayPauseButton.setOnClickListener(this);
|
mPlayPauseButton.setOnClickListener(this);
|
||||||
View nextButton = findViewById(R.id.next);
|
View nextButton = findViewById(R.id.next);
|
||||||
nextButton.setOnClickListener(this);
|
nextButton.setOnClickListener(this);
|
||||||
@ -103,7 +102,7 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
if (state == mState)
|
if (state == mState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mState = state;
|
super.setState(state);
|
||||||
|
|
||||||
if (mMessageOverlay != null)
|
if (mMessageOverlay != null)
|
||||||
mMessageOverlay.setVisibility(View.GONE);
|
mMessageOverlay.setVisibility(View.GONE);
|
||||||
@ -130,11 +129,6 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
text.setLayoutParams(layoutParams);
|
text.setLayoutParams(layoutParams);
|
||||||
mMessageOverlay.addView(text);
|
mMessageOverlay.addView(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mState & PlaybackService.FLAG_PLAYING) != 0)
|
|
||||||
mPlayPauseButton.setImageResource(R.drawable.pause);
|
|
||||||
else
|
|
||||||
mPlayPauseButton.setImageResource(R.drawable.play);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -152,7 +146,7 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
|
|
||||||
if (PlaybackService.EVENT_CHANGED.equals(intent.getAction())) {
|
if (PlaybackService.EVENT_CHANGED.equals(intent.getAction())) {
|
||||||
mDuration = ContextApplication.service.getDuration();
|
mDuration = ContextApplication.service.getDuration();
|
||||||
mHandler.sendEmptyMessage(MSG_UPDATE_PROGRESS);
|
mUiHandler.sendEmptyMessage(MSG_UPDATE_PROGRESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,10 +228,10 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
|
|
||||||
// Try to update right when the duration increases by one second
|
// Try to update right when the duration increases by one second
|
||||||
long next = 1000 - position % 1000;
|
long next = 1000 - position % 1000;
|
||||||
mHandler.removeMessages(MSG_UPDATE_PROGRESS);
|
mUiHandler.removeMessages(MSG_UPDATE_PROGRESS);
|
||||||
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_PROGRESS, next);
|
mUiHandler.sendEmptyMessageDelayed(MSG_UPDATE_PROGRESS, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view)
|
public void onClick(View view)
|
||||||
{
|
{
|
||||||
@ -265,13 +259,10 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
public boolean handleMessage(Message message)
|
public boolean handleMessage(Message message)
|
||||||
{
|
{
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case MSG_UPDATE_PROGRESS:
|
|
||||||
updateProgress();
|
|
||||||
return true;
|
|
||||||
case MSG_SAVE_DISPLAY_MODE:
|
case MSG_SAVE_DISPLAY_MODE:
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(FullPlaybackActivity.this);
|
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(FullPlaybackActivity.this);
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
SharedPreferences.Editor editor = settings.edit();
|
||||||
editor.putBoolean("separate_info", mCoverView.hasSeparateInfo());
|
editor.putBoolean("separate_info", mCoverView.mSeparateInfo);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@ -279,6 +270,18 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Handler mUiHandler = new Handler() {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message message)
|
||||||
|
{
|
||||||
|
switch (message.what) {
|
||||||
|
case MSG_UPDATE_PROGRESS:
|
||||||
|
updateProgress();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||||
{
|
{
|
||||||
if (fromUser)
|
if (fromUser)
|
||||||
@ -294,4 +297,4 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On
|
|||||||
{
|
{
|
||||||
mSeekBarTracking = false;
|
mSeekBarTracking = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,15 +27,12 @@ import android.util.AttributeSet;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playback activity that displays itself like a dialog, i.e. as a small window
|
* Playback activity that displays itself like a dialog, i.e. as a small window
|
||||||
* with a border. Includes a CoverView and control buttons.
|
* with a border. Includes a CoverView and control buttons.
|
||||||
*/
|
*/
|
||||||
public class MiniPlaybackActivity extends PlaybackActivity implements View.OnClickListener {
|
public class MiniPlaybackActivity extends PlaybackActivity implements View.OnClickListener {
|
||||||
private ImageView mPlayPauseButton;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle state)
|
public void onCreate(Bundle state)
|
||||||
{
|
{
|
||||||
@ -45,6 +42,7 @@ public class MiniPlaybackActivity extends PlaybackActivity implements View.OnCli
|
|||||||
setContentView(R.layout.mini_playback);
|
setContentView(R.layout.mini_playback);
|
||||||
|
|
||||||
mCoverView = (CoverView)findViewById(R.id.cover_view);
|
mCoverView = (CoverView)findViewById(R.id.cover_view);
|
||||||
|
mCoverView.mHandler = mHandler;
|
||||||
|
|
||||||
View openButton = findViewById(R.id.open_button);
|
View openButton = findViewById(R.id.open_button);
|
||||||
openButton.setOnClickListener(this);
|
openButton.setOnClickListener(this);
|
||||||
@ -52,21 +50,12 @@ public class MiniPlaybackActivity extends PlaybackActivity implements View.OnCli
|
|||||||
killButton.setOnClickListener(this);
|
killButton.setOnClickListener(this);
|
||||||
View previousButton = findViewById(R.id.previous);
|
View previousButton = findViewById(R.id.previous);
|
||||||
previousButton.setOnClickListener(this);
|
previousButton.setOnClickListener(this);
|
||||||
mPlayPauseButton = (ImageView)findViewById(R.id.play_pause);
|
mPlayPauseButton = (ControlButton)findViewById(R.id.play_pause);
|
||||||
mPlayPauseButton.setOnClickListener(this);
|
mPlayPauseButton.setOnClickListener(this);
|
||||||
View nextButton = findViewById(R.id.next);
|
View nextButton = findViewById(R.id.next);
|
||||||
nextButton.setOnClickListener(this);
|
nextButton.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setState(int state)
|
|
||||||
{
|
|
||||||
if ((state & PlaybackService.FLAG_NO_MEDIA) != 0)
|
|
||||||
finish();
|
|
||||||
|
|
||||||
mPlayPauseButton.setImageResource((state & PlaybackService.FLAG_PLAYING) == 0 ? R.drawable.play : R.drawable.pause);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view)
|
public void onClick(View view)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,8 @@ import android.app.Activity;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@ -30,9 +32,11 @@ import android.view.View;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class PlaybackActivity extends Activity implements Handler.Callback, View.OnClickListener {
|
public class PlaybackActivity extends Activity implements Handler.Callback, View.OnClickListener {
|
||||||
Handler mHandler = new Handler(this);
|
Handler mHandler;
|
||||||
|
Looper mLooper;
|
||||||
|
|
||||||
CoverView mCoverView;
|
CoverView mCoverView;
|
||||||
|
ControlButton mPlayPauseButton;
|
||||||
int mState;
|
int mState;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -40,6 +44,12 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
{
|
{
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
ContextApplication.addActivity(this);
|
ContextApplication.addActivity(this);
|
||||||
|
|
||||||
|
HandlerThread thread = new HandlerThread(getClass().getName());
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
mLooper = thread.getLooper();
|
||||||
|
mHandler = new Handler(mLooper, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -47,6 +57,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
{
|
{
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
ContextApplication.removeActivity(this);
|
ContextApplication.removeActivity(this);
|
||||||
|
mLooper.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -55,6 +66,8 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
startService(new Intent(this, PlaybackService.class));
|
startService(new Intent(this, PlaybackService.class));
|
||||||
|
if (ContextApplication.service != null)
|
||||||
|
onServiceReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean handleKeyLongPress(int keyCode)
|
public static boolean handleKeyLongPress(int keyCode)
|
||||||
@ -78,30 +91,43 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
{
|
{
|
||||||
switch (view.getId()) {
|
switch (view.getId()) {
|
||||||
case R.id.next:
|
case R.id.next:
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_SONG, 1, 0));
|
||||||
if (mCoverView != null)
|
if (mCoverView != null)
|
||||||
mCoverView.go(1);
|
mCoverView.go(1);
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_SONG, 1, 0));
|
|
||||||
break;
|
break;
|
||||||
case R.id.play_pause:
|
case R.id.play_pause:
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_TOGGLE_FLAG, PlaybackService.FLAG_PLAYING, 0));
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_TOGGLE_FLAG, PlaybackService.FLAG_PLAYING, 0));
|
||||||
break;
|
break;
|
||||||
case R.id.previous:
|
case R.id.previous:
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_SONG, -1, 0));
|
||||||
if (mCoverView != null)
|
if (mCoverView != null)
|
||||||
mCoverView.go(-1);
|
mCoverView.go(-1);
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_SONG, -1, 0));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets <code>mState</code> to <code>state</code>. Override to implement
|
* Updates <code>mState</code> and the play/pause button. Override to
|
||||||
* further behavior in subclasses.
|
* implement further behavior in subclasses.
|
||||||
*
|
*
|
||||||
* @param state PlaybackService state
|
* @param state PlaybackService state
|
||||||
*/
|
*/
|
||||||
protected void setState(int state)
|
protected void setState(int state)
|
||||||
{
|
{
|
||||||
|
if (mState == state)
|
||||||
|
return;
|
||||||
|
|
||||||
mState = state;
|
mState = state;
|
||||||
|
|
||||||
|
if (mPlayPauseButton != null) {
|
||||||
|
final int res = (mState & PlaybackService.FLAG_PLAYING) == 0 ? R.drawable.play : R.drawable.pause;
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
mPlayPauseButton.setImageResource(res);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,7 +138,6 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View
|
|||||||
{
|
{
|
||||||
if (mCoverView != null)
|
if (mCoverView != null)
|
||||||
mCoverView.initialize();
|
mCoverView.initialize();
|
||||||
|
|
||||||
setState(ContextApplication.service.getState());
|
setState(ContextApplication.service.getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ import android.content.res.Resources;
|
|||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.PaintDrawable;
|
import android.graphics.drawable.PaintDrawable;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
@ -60,8 +59,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
private View mClearButton;
|
private View mClearButton;
|
||||||
|
|
||||||
private View mStatus;
|
private View mStatus;
|
||||||
private TextView mStatusText;
|
TextView mStatusText;
|
||||||
private ControlButton mPlayPauseButton;
|
|
||||||
|
|
||||||
private ViewGroup mLimiterViews;
|
private ViewGroup mLimiterViews;
|
||||||
|
|
||||||
@ -76,14 +74,6 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
return (MediaAdapter)list.getAdapter();
|
return (MediaAdapter)list.getAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeList(int id, Uri store, String[] fields, String[] fieldKeys)
|
|
||||||
{
|
|
||||||
ListView view = (ListView)findViewById(id);
|
|
||||||
view.setOnItemClickListener(this);
|
|
||||||
view.setOnCreateContextMenuListener(this);
|
|
||||||
view.setAdapter(new MediaAdapter(this, store, fields, fieldKeys, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle state)
|
public void onCreate(Bundle state)
|
||||||
{
|
{
|
||||||
@ -133,6 +123,11 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
|
|
||||||
mPlayPauseButton.setOnClickListener(this);
|
mPlayPauseButton.setOnClickListener(this);
|
||||||
next.setOnClickListener(this);
|
next.setOnClickListener(this);
|
||||||
|
|
||||||
|
if (ContextApplication.service != null) {
|
||||||
|
setState(ContextApplication.service.getState());
|
||||||
|
onSongChange(ContextApplication.service.getSong(0));
|
||||||
|
}
|
||||||
} else if (!status && mStatus != null) {
|
} else if (!status && mStatus != null) {
|
||||||
mStatus.setVisibility(View.GONE);
|
mStatus.setVisibility(View.GONE);
|
||||||
mStatus = null;
|
mStatus = null;
|
||||||
@ -376,6 +371,25 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
getAdapter(i).filter(text, null);
|
getAdapter(i).filter(text, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook up a ListView to this Activity and the supplied adapter
|
||||||
|
*
|
||||||
|
* @param id The id of the ListView
|
||||||
|
* @param adapter The adapter to be used
|
||||||
|
*/
|
||||||
|
private void setupView(int id, final MediaAdapter adapter)
|
||||||
|
{
|
||||||
|
final ListView view = (ListView)findViewById(id);
|
||||||
|
view.setOnItemClickListener(this);
|
||||||
|
view.setOnCreateContextMenuListener(this);
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
view.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static final int MSG_INIT = 10;
|
private static final int MSG_INIT = 10;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -383,13 +397,9 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
{
|
{
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case MSG_INIT:
|
case MSG_INIT:
|
||||||
initializeList(R.id.artist_list, MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, MediaAdapter.ARTIST_FIELDS, MediaAdapter.ARTIST_FIELD_KEYS);
|
setupView(R.id.artist_list, new MediaAdapter(this, MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, MediaAdapter.ARTIST_FIELDS, MediaAdapter.ARTIST_FIELD_KEYS, true));
|
||||||
initializeList(R.id.album_list, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, MediaAdapter.ALBUM_FIELDS, MediaAdapter.ALBUM_FIELD_KEYS);
|
setupView(R.id.album_list, new MediaAdapter(this, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, MediaAdapter.ALBUM_FIELDS, MediaAdapter.ALBUM_FIELD_KEYS, true));
|
||||||
|
setupView(R.id.song_list, new SongMediaAdapter(this));
|
||||||
ListView view = (ListView)findViewById(R.id.song_list);
|
|
||||||
view.setOnItemClickListener(SongSelector.this);
|
|
||||||
view.setOnCreateContextMenuListener(SongSelector.this);
|
|
||||||
view.setAdapter(new SongMediaAdapter(this));
|
|
||||||
|
|
||||||
ContentResolver resolver = getContentResolver();
|
ContentResolver resolver = getContentResolver();
|
||||||
resolver.registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mObserver);
|
resolver.registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mObserver);
|
||||||
@ -421,10 +431,16 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
/**
|
/**
|
||||||
* Call to update the status text for a newly-playing song.
|
* Call to update the status text for a newly-playing song.
|
||||||
*/
|
*/
|
||||||
private void onSongChange(Song song)
|
private void onSongChange(final Song song)
|
||||||
{
|
{
|
||||||
if (mStatusText != null)
|
if (mStatusText != null) {
|
||||||
mStatusText.setText(song == null ? getResources().getText(R.string.none) : song.title);
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
mStatusText.setText(song == null ? getResources().getText(R.string.none) : song.title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -435,13 +451,4 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem
|
|||||||
onSongChange(song);
|
onSongChange(song);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setState(int state)
|
|
||||||
{
|
|
||||||
if (mPlayPauseButton != null) {
|
|
||||||
boolean playing = (state & PlaybackService.FLAG_PLAYING) != 0;
|
|
||||||
mPlayPauseButton.setImageResource(playing ? R.drawable.pause : R.drawable.play);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user