Allow NowPlayingActivity to stop the playback service
This commit is contained in:
parent
197d529fe6
commit
40ebd4ec1b
@ -26,6 +26,6 @@
|
|||||||
android:id="@+id/kill_button"
|
android:id="@+id/kill_button"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:text="Kill Service" />
|
android:text="Quit Service" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</org.kreed.tumult.RemoteLayout>
|
</org.kreed.tumult.RemoteLayout>
|
@ -5,6 +5,7 @@ import org.kreed.tumult.IMusicPlayerWatcher;
|
|||||||
|
|
||||||
interface IPlaybackService {
|
interface IPlaybackService {
|
||||||
void registerWatcher(IMusicPlayerWatcher watcher);
|
void registerWatcher(IMusicPlayerWatcher watcher);
|
||||||
|
void unregisterWatcher(IMusicPlayerWatcher watcher);
|
||||||
|
|
||||||
Song[] getCurrentSongs();
|
Song[] getCurrentSongs();
|
||||||
Song getSong(int delta);
|
Song getSong(int delta);
|
||||||
|
@ -90,6 +90,12 @@ public class MusicPlayer implements Runnable, MediaPlayer.OnCompletionListener,
|
|||||||
mWatchers.register(watcher);
|
mWatchers.register(watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void unregisterWatcher(IMusicPlayerWatcher watcher)
|
||||||
|
{
|
||||||
|
if (watcher != null)
|
||||||
|
mWatchers.unregister(watcher);
|
||||||
|
}
|
||||||
|
|
||||||
public void seekToProgress(int progress)
|
public void seekToProgress(int progress)
|
||||||
{
|
{
|
||||||
if (mMediaPlayer == null || !mMediaPlayer.isPlaying())
|
if (mMediaPlayer == null || !mMediaPlayer.isPlaying())
|
||||||
|
@ -12,14 +12,15 @@ import android.os.IBinder;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
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.Button;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
|
|
||||||
private ViewGroup mLayout;
|
private ViewGroup mLayout;
|
||||||
private CoverView mCoverView;
|
private CoverView mCoverView;
|
||||||
private LinearLayout mMessageBox;
|
private RelativeLayout mMessageOverlay;
|
||||||
private View mControlsTop;
|
private View mControlsTop;
|
||||||
private View mControlsBottom;
|
private View mControlsBottom;
|
||||||
|
|
||||||
@ -37,11 +38,13 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
private ImageButton mNextButton;
|
private ImageButton mNextButton;
|
||||||
private SeekBar mSeekBar;
|
private SeekBar mSeekBar;
|
||||||
private TextView mSeekText;
|
private TextView mSeekText;
|
||||||
|
private Button mReconnectButton;
|
||||||
|
|
||||||
private int mState;
|
private int mState;
|
||||||
private int mDuration;
|
private int mDuration;
|
||||||
private boolean mSeekBarTracking;
|
private boolean mSeekBarTracking;
|
||||||
|
|
||||||
|
private static final int MENU_KILL = 0;
|
||||||
private static final int MENU_PREFS = 2;
|
private static final int MENU_PREFS = 2;
|
||||||
private static final int MENU_QUEUE = 3;
|
private static final int MENU_QUEUE = 3;
|
||||||
|
|
||||||
@ -76,89 +79,156 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
mSeekBar.setOnSeekBarChangeListener(this);
|
mSeekBar.setOnSeekBarChangeListener(this);
|
||||||
mSeekBar.setOnFocusChangeListener(this);
|
mSeekBar.setOnFocusChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void makeMessageOverlay()
|
||||||
|
{
|
||||||
|
if (mMessageOverlay != null) {
|
||||||
|
mMessageOverlay.removeAllViews();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewGroup.LayoutParams layoutParams =
|
||||||
|
new ViewGroup.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
|
||||||
|
LinearLayout.LayoutParams.FILL_PARENT);
|
||||||
|
|
||||||
|
mMessageOverlay = new RelativeLayout(this);
|
||||||
|
mMessageOverlay.setLayoutParams(layoutParams);
|
||||||
|
mMessageOverlay.setBackgroundColor(Color.BLACK);
|
||||||
|
|
||||||
|
mLayout.addView(mMessageOverlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeMessageOverlay()
|
||||||
|
{
|
||||||
|
mReconnectButton = null;
|
||||||
|
|
||||||
|
if (mMessageOverlay != null) {
|
||||||
|
mLayout.removeView(mMessageOverlay);
|
||||||
|
mMessageOverlay = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setState(int state)
|
public void setState(int state)
|
||||||
{
|
{
|
||||||
mState = state;
|
mState = state;
|
||||||
|
|
||||||
|
if (mService == null) {
|
||||||
|
makeMessageOverlay();
|
||||||
|
|
||||||
|
RelativeLayout.LayoutParams layoutParams =
|
||||||
|
new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||||
|
|
||||||
|
mReconnectButton = new Button(this);
|
||||||
|
mReconnectButton.setText("Connect to Service");
|
||||||
|
mReconnectButton.setLayoutParams(layoutParams);
|
||||||
|
mReconnectButton.setOnClickListener(this);
|
||||||
|
mMessageOverlay.addView(mReconnectButton);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case MusicPlayer.STATE_NORMAL:
|
case MusicPlayer.STATE_NORMAL:
|
||||||
mControlsBottom.setVisibility(View.VISIBLE);
|
mControlsBottom.setVisibility(View.VISIBLE);
|
||||||
// fall through
|
// fall through
|
||||||
case MusicPlayer.STATE_PLAYING:
|
case MusicPlayer.STATE_PLAYING:
|
||||||
if (mMessageBox != null) {
|
removeMessageOverlay();
|
||||||
mLayout.removeView(mMessageBox);
|
|
||||||
mMessageBox = null;
|
if (!mHandler.hasMessages(HIDE))
|
||||||
}
|
mControlsBottom.setVisibility(View.GONE);
|
||||||
|
|
||||||
mSeekBar.setEnabled(state == MusicPlayer.STATE_PLAYING);
|
mSeekBar.setEnabled(state == MusicPlayer.STATE_PLAYING);
|
||||||
mPlayPauseButton.setImageResource(state == MusicPlayer.STATE_PLAYING ? R.drawable.pause : R.drawable.play);
|
mPlayPauseButton.setImageResource(state == MusicPlayer.STATE_PLAYING ? R.drawable.pause : R.drawable.play);
|
||||||
break;
|
break;
|
||||||
case MusicPlayer.STATE_NO_MEDIA:
|
case MusicPlayer.STATE_NO_MEDIA:
|
||||||
LinearLayout.LayoutParams layoutParams =
|
makeMessageOverlay();
|
||||||
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
|
|
||||||
LinearLayout.LayoutParams.FILL_PARENT);
|
RelativeLayout.LayoutParams layoutParams =
|
||||||
layoutParams.gravity = Gravity.CENTER;
|
new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||||
|
|
||||||
TextView text = new TextView(this);
|
TextView text = new TextView(this);
|
||||||
text.setText("No songs found on your device.");
|
text.setText("No songs found on your device.");
|
||||||
text.setGravity(Gravity.CENTER);
|
|
||||||
text.setLayoutParams(layoutParams);
|
text.setLayoutParams(layoutParams);
|
||||||
|
mMessageOverlay.addView(text);
|
||||||
mMessageBox = new LinearLayout(this);
|
|
||||||
mMessageBox.setLayoutParams(layoutParams);
|
|
||||||
mMessageBox.setBackgroundColor(Color.BLACK);
|
|
||||||
mMessageBox.addView(text);
|
|
||||||
|
|
||||||
mLayout.addView(mMessageBox);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume()
|
public void onStart()
|
||||||
{
|
{
|
||||||
super.onResume();
|
super.onStart();
|
||||||
|
|
||||||
reconnect();
|
prepareService();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reconnect()
|
@Override
|
||||||
|
public void onStop()
|
||||||
|
{
|
||||||
|
super.onStop();
|
||||||
|
|
||||||
|
if (mService != null) {
|
||||||
|
unbindService(this);
|
||||||
|
mHandler.sendEmptyMessage(UNSET_SERVICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareService()
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(this, PlaybackService.class);
|
Intent intent = new Intent(this, PlaybackService.class);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
bindService(intent, this, Context.BIND_AUTO_CREATE);
|
bindService(intent, this, Context.BIND_AUTO_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void setService(IPlaybackService service)
|
||||||
public void onPause()
|
|
||||||
{
|
{
|
||||||
super.onPause();
|
if (service == mService)
|
||||||
|
return;
|
||||||
|
|
||||||
unbindService(this);
|
int state = mState;
|
||||||
|
|
||||||
|
if (service == null) {
|
||||||
|
if (mService != null)
|
||||||
|
try {
|
||||||
|
mService.unregisterWatcher(mWatcher);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
service.registerWatcher(mWatcher);
|
||||||
|
mCoverView.setPlaybackService(service);
|
||||||
|
state = service.getState();
|
||||||
|
mDuration = service.getDuration();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.i("Tumult", "Failed to initialize connection to playback service", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mService = service;
|
||||||
|
setState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceConnected(ComponentName name, IBinder service)
|
public void onServiceConnected(ComponentName name, IBinder service)
|
||||||
{
|
{
|
||||||
mService = IPlaybackService.Stub.asInterface(service);
|
setService(IPlaybackService.Stub.asInterface(service));
|
||||||
try {
|
|
||||||
mService.registerWatcher(mWatcher);
|
|
||||||
mCoverView.setPlaybackService(mService);
|
|
||||||
setState(mService.getState());
|
|
||||||
mDuration = mService.getDuration();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.i("Tumult", "Failed to initialize connection to playback service", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName name)
|
public void onServiceDisconnected(ComponentName name)
|
||||||
{
|
{
|
||||||
mService = null;
|
setService(null);
|
||||||
reconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMusicPlayerWatcher mWatcher = new IMusicPlayerWatcher.Stub() {
|
private IMusicPlayerWatcher mWatcher = new IMusicPlayerWatcher.Stub() {
|
||||||
public void songChanged(Song playingSong)
|
public void songChanged(Song playingSong)
|
||||||
{
|
{
|
||||||
|
if (mService == null)
|
||||||
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mDuration = mService.getDuration();
|
mDuration = mService.getDuration();
|
||||||
mHandler.sendEmptyMessage(UPDATE_PROGRESS);
|
mHandler.sendEmptyMessage(UPDATE_PROGRESS);
|
||||||
@ -182,13 +252,26 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
{
|
{
|
||||||
menu.add(0, MENU_PREFS, 0, "Preferences");
|
menu.add(0, MENU_PREFS, 0, "Preferences");
|
||||||
menu.add(0, MENU_QUEUE, 0, "Add to Queue");
|
menu.add(0, MENU_QUEUE, 0, "Add to Queue");
|
||||||
|
menu.add(0, MENU_KILL, 0, "Quit Service");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareOptionsMenu(Menu menu)
|
||||||
|
{
|
||||||
|
menu.findItem(MENU_KILL).setEnabled(mService != null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem item)
|
public boolean onOptionsItemSelected(final MenuItem item)
|
||||||
{
|
{
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case MENU_KILL:
|
||||||
|
setService(null);
|
||||||
|
unbindService(this);
|
||||||
|
stopService(new Intent(this, PlaybackService.class));
|
||||||
|
break;
|
||||||
case MENU_PREFS:
|
case MENU_PREFS:
|
||||||
startActivity(new Intent(this, PreferencesActivity.class));
|
startActivity(new Intent(this, PreferencesActivity.class));
|
||||||
break;
|
break;
|
||||||
@ -240,11 +323,12 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
if (mControlsTop.getVisibility() != View.VISIBLE)
|
if (mControlsTop.getVisibility() != View.VISIBLE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int position;
|
int position = 0;
|
||||||
try {
|
if (mService != null) {
|
||||||
position = mService.getPosition();
|
try {
|
||||||
} catch (RemoteException e) {
|
position = mService.getPosition();
|
||||||
return;
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSeekBarTracking)
|
if (!mSeekBarTracking)
|
||||||
@ -285,11 +369,14 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
mCoverView.previousCover();
|
mCoverView.previousCover();
|
||||||
} else if (view == mPlayPauseButton) {
|
} else if (view == mPlayPauseButton) {
|
||||||
mCoverView.togglePlayback();
|
mCoverView.togglePlayback();
|
||||||
|
} else if (view == mReconnectButton) {
|
||||||
|
prepareService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int HIDE = 0;
|
private static final int HIDE = 0;
|
||||||
private static final int UPDATE_PROGRESS = 1;
|
private static final int UPDATE_PROGRESS = 1;
|
||||||
|
private static final int UNSET_SERVICE = 2;
|
||||||
|
|
||||||
private Handler mHandler = new Handler() {
|
private Handler mHandler = new Handler() {
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
@ -302,17 +389,21 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
|
|||||||
case UPDATE_PROGRESS:
|
case UPDATE_PROGRESS:
|
||||||
updateProgress();
|
updateProgress();
|
||||||
break;
|
break;
|
||||||
|
case UNSET_SERVICE:
|
||||||
|
setService(null);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||||
{
|
{
|
||||||
if (fromUser) {
|
if (!fromUser || mService == null)
|
||||||
try {
|
return;
|
||||||
mService.seekToProgress(progress);
|
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
}
|
mService.seekToProgress(progress);
|
||||||
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user