Use broadcasts instead of callbacks in PlaybackService

This commit is contained in:
Christopher Eby 2010-03-06 21:28:58 -06:00
parent acd259e305
commit a87a185c3c
5 changed files with 86 additions and 122 deletions

View File

@ -18,10 +18,12 @@
package org.kreed.vanilla; package org.kreed.vanilla;
import org.kreed.vanilla.IMusicPlayerWatcher;
import org.kreed.vanilla.IPlaybackService; import org.kreed.vanilla.IPlaybackService;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
@ -49,7 +51,6 @@ public class CoverView extends View {
private float mStartX; private float mStartX;
private float mStartY; private float mStartY;
private IPlaybackService mService; private IPlaybackService mService;
private boolean loaded;
Song[] mSongs = new Song[3]; Song[] mSongs = new Song[3];
private Bitmap[] mBitmaps = new Bitmap[3]; private Bitmap[] mBitmaps = new Bitmap[3];
@ -61,13 +62,19 @@ public class CoverView extends View {
super(context, attributes); super(context, attributes);
mScroller = new Scroller(context); mScroller = new Scroller(context);
IntentFilter filter = new IntentFilter();
filter.addAction(PlaybackService.EVENT_LOADED);
filter.addAction(PlaybackService.EVENT_SONG_CHANGED);
context.registerReceiver(mReceiver, filter);
} }
public void setPlaybackService(IPlaybackService service) public void setPlaybackService(IPlaybackService service)
{ {
try { try {
mService = service; mService = service;
mService.registerWatcher(mWatcher); if (mService.isLoaded())
refreshSongs();
} catch (RemoteException e) { } catch (RemoteException e) {
} }
} }
@ -279,8 +286,6 @@ public class CoverView extends View {
{ {
if (mService == null) if (mService == null)
throw new RemoteException(); throw new RemoteException();
if (delta != 0 && !loaded)
return;
mHandler.sendMessage(mHandler.obtainMessage(GO, delta, 0)); mHandler.sendMessage(mHandler.obtainMessage(GO, delta, 0));
} }
@ -289,7 +294,7 @@ public class CoverView extends View {
if (!mScroller.isFinished()) if (!mScroller.isFinished())
mScroller.abortAnimation(); mScroller.abortAnimation();
scrollTo(getWidth(), 0); scrollTo(getWidth(), 0);
postInvalidate(); invalidate();
} }
@Override @Override
@ -449,24 +454,22 @@ public class CoverView extends View {
} }
}; };
private IMusicPlayerWatcher mWatcher = new IMusicPlayerWatcher.Stub() { private BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void loaded() @Override
public void onReceive(Context context, Intent intent)
{ {
loaded = true; String action = intent.getAction();
refreshSongs();
}
public void songChanged(Song playingSong) if (PlaybackService.EVENT_LOADED.equals(action)) {
{ refreshSongs();
} else if (PlaybackService.EVENT_SONG_CHANGED.equals(action)) {
Song currentSong = mSongs[STORE_SIZE / 2]; Song currentSong = mSongs[STORE_SIZE / 2];
Song playingSong = intent.getParcelableExtra("song");
if (currentSong == null) if (currentSong == null)
mHandler.sendMessage(mHandler.obtainMessage(SET_COVER, playingSong)); mHandler.sendMessage(mHandler.obtainMessage(SET_COVER, playingSong));
else if (!currentSong.equals(playingSong)) else if (!currentSong.equals(playingSong))
refreshSongs(); refreshSongs();
} }
public void stateChanged(int oldState, int newState)
{
} }
}; };
} }

View File

@ -19,11 +19,9 @@
package org.kreed.vanilla; package org.kreed.vanilla;
import org.kreed.vanilla.Song; import org.kreed.vanilla.Song;
import org.kreed.vanilla.IMusicPlayerWatcher;
interface IPlaybackService { interface IPlaybackService {
void registerWatcher(IMusicPlayerWatcher watcher); boolean isLoaded();
void unregisterWatcher(IMusicPlayerWatcher watcher);
Song getSong(int delta); Song getSong(int delta);
int getState(); int getState();

View File

@ -18,14 +18,15 @@
package org.kreed.vanilla; package org.kreed.vanilla;
import org.kreed.vanilla.IMusicPlayerWatcher;
import org.kreed.vanilla.IPlaybackService; import org.kreed.vanilla.IPlaybackService;
import org.kreed.vanilla.R; import org.kreed.vanilla.R;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
@ -187,6 +188,11 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
super.onStart(); super.onStart();
prepareService(); prepareService();
IntentFilter filter = new IntentFilter();
filter.addAction(PlaybackService.EVENT_SONG_CHANGED);
filter.addAction(PlaybackService.EVENT_STATE_CHANGED);
registerReceiver(mReceiver, filter);
} }
@Override @Override
@ -196,6 +202,11 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
if (mService != null) { if (mService != null) {
unbindService(this); unbindService(this);
try {
unregisterReceiver(mReceiver);
} catch (IllegalArgumentException e) {
// we haven't registered the receiver yet
}
mHandler.sendEmptyMessage(UNSET_SERVICE); mHandler.sendEmptyMessage(UNSET_SERVICE);
} }
} }
@ -215,15 +226,9 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
int state = mState; int state = mState;
if (service == null) { if (service == null) {
if (mService != null)
try {
mService.unregisterWatcher(mWatcher);
} catch (RemoteException e) {
}
mCoverView.clearSongs(); mCoverView.clearSongs();
} else { } else {
try { try {
service.registerWatcher(mWatcher);
mCoverView.setPlaybackService(service); mCoverView.setPlaybackService(service);
state = service.getState(); state = service.getState();
mDuration = service.getDuration(); mDuration = service.getDuration();
@ -247,31 +252,21 @@ public class NowPlayingActivity extends Activity implements ServiceConnection, V
setService(null); setService(null);
} }
private IMusicPlayerWatcher mWatcher = new IMusicPlayerWatcher.Stub() { private BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void loaded() @Override
public void onReceive(Context context, Intent intent)
{ {
} String action = intent.getAction();
if (PlaybackService.EVENT_SONG_CHANGED.equals(action)) {
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);
} catch (RemoteException e) { } catch (RemoteException e) {
setService(null);
} }
} else if (PlaybackService.EVENT_STATE_CHANGED.equals(action)) {
setState(intent.getIntExtra("newState", 0));
} }
public void stateChanged(final int oldState, final int newState)
{
runOnUiThread(new Runnable() {
public void run()
{
setState(newState);
}
});
} }
}; };

View File

@ -27,7 +27,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random; import java.util.Random;
import org.kreed.vanilla.IMusicPlayerWatcher;
import org.kreed.vanilla.IPlaybackService; import org.kreed.vanilla.IPlaybackService;
import org.kreed.vanilla.R; import org.kreed.vanilla.R;
@ -48,8 +47,6 @@ import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener; import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
@ -64,13 +61,20 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
public static final String TOGGLE_PLAYBACK = "org.kreed.vanilla.action.TOGGLE_PLAYBACK"; public static final String TOGGLE_PLAYBACK = "org.kreed.vanilla.action.TOGGLE_PLAYBACK";
public static final String NEXT_SONG = "org.kreed.vanilla.action.NEXT_SONG"; public static final String NEXT_SONG = "org.kreed.vanilla.action.NEXT_SONG";
public static final String EVENT_LOADED = "org.kreed.vanilla.event.LOADED";
public static final String EVENT_STATE_CHANGED = "org.kreed.vanilla.event.STATE_CHANGED";
public static final String EVENT_SONG_CHANGED = "org.kreed.vanilla.event.SONG_CHANGED";
public static final int STATE_NORMAL = 0; public static final int STATE_NORMAL = 0;
public static final int STATE_NO_MEDIA = 1; public static final int STATE_NO_MEDIA = 1;
public static final int STATE_PLAYING = 2; public static final int STATE_PLAYING = 2;
private RemoteCallbackList<IMusicPlayerWatcher> mWatchers;
public IPlaybackService.Stub mBinder = new IPlaybackService.Stub() { public IPlaybackService.Stub mBinder = new IPlaybackService.Stub() {
public boolean isLoaded()
{
return mHandler != null;
}
public Song getSong(int delta) public Song getSong(int delta)
{ {
return PlaybackService.this.getSong(delta); return PlaybackService.this.getSong(delta);
@ -111,22 +115,6 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
mHandler.sendMessage(mHandler.obtainMessage(GO, 0, 0)); mHandler.sendMessage(mHandler.obtainMessage(GO, 0, 0));
} }
public void registerWatcher(IMusicPlayerWatcher watcher) throws RemoteException
{
if (watcher != null) {
mWatchers.register(watcher);
// if we're already loaded callback immediately
if (mHandler != null)
watcher.loaded();
}
}
public void unregisterWatcher(IMusicPlayerWatcher watcher)
{
if (watcher != null)
mWatchers.unregister(watcher);
}
public void seekToProgress(int progress) public void seekToProgress(int progress)
{ {
if (mMediaPlayer == null) if (mMediaPlayer == null)
@ -149,8 +137,6 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
@Override @Override
public void onCreate() public void onCreate()
{ {
mWatchers = new RemoteCallbackList<IMusicPlayerWatcher>();
new Thread(this).start(); new Thread(this).start();
} }
@ -182,7 +168,11 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
player.release(); player.release();
} }
try {
unregisterReceiver(mReceiver); unregisterReceiver(mReceiver);
} catch (IllegalArgumentException e) {
// we haven't registered the receiver yet
}
mNotificationManager.cancel(NOTIFICATION_ID); mNotificationManager.cancel(NOTIFICATION_ID);
resetWidgets(); resetWidgets();
@ -415,14 +405,7 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
if (mPendingSeek != 0) if (mPendingSeek != 0)
mMediaPlayer.seekTo(mPendingSeek); mMediaPlayer.seekTo(mPendingSeek);
int i = mWatchers.beginBroadcast(); sendBroadcast(new Intent(EVENT_LOADED));
while (--i != -1) {
try {
mWatchers.getBroadcastItem(i).loaded();
} catch (RemoteException e) {
}
}
mWatchers.finishBroadcast();
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_HEADSET_PLUG); filter.addAction(Intent.ACTION_HEADSET_PLUG);
@ -467,15 +450,10 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
mState = state; mState = state;
if (mState != oldState) { if (mState != oldState) {
int i = mWatchers.beginBroadcast(); Intent intent = new Intent(EVENT_STATE_CHANGED);
while (--i != -1) { intent.putExtra("oldState", oldState);
try { intent.putExtra("newState", state);
mWatchers.getBroadcastItem(i).stateChanged(oldState, mState); sendBroadcast(intent);
} catch (RemoteException e) {
// Null elements will be removed automatically
}
}
mWatchers.finishBroadcast();
} }
Song song = getSong(0); Song song = getSong(0);
@ -596,15 +574,9 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On
mLastSongBroadcast = song; mLastSongBroadcast = song;
int i = mWatchers.beginBroadcast(); Intent intent = new Intent(EVENT_SONG_CHANGED);
while (--i != -1) { intent.putExtra("song", song);
try { sendBroadcast(intent);
mWatchers.getBroadcastItem(i).songChanged(song);
} catch (RemoteException e) {
// Null elements will be removed automatically
}
}
mWatchers.finishBroadcast();
} }
private void setCurrentSong(int delta) private void setCurrentSong(int delta)

View File

@ -18,14 +18,15 @@
package org.kreed.vanilla; package org.kreed.vanilla;
import org.kreed.vanilla.IMusicPlayerWatcher;
import org.kreed.vanilla.IPlaybackService; import org.kreed.vanilla.IPlaybackService;
import org.kreed.vanilla.R; import org.kreed.vanilla.R;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
@ -72,6 +73,7 @@ public class RemoteActivity extends Activity implements ServiceConnection, View.
super.onResume(); super.onResume();
reconnect(); reconnect();
registerReceiver(mReceiver, new IntentFilter(PlaybackService.EVENT_STATE_CHANGED));
} }
private void reconnect() private void reconnect()
@ -87,6 +89,11 @@ public class RemoteActivity extends Activity implements ServiceConnection, View.
super.onPause(); super.onPause();
unbindService(this); unbindService(this);
try {
unregisterReceiver(mReceiver);
} catch (IllegalArgumentException e) {
// we haven't registered the receiver yet
}
} }
public void onServiceConnected(ComponentName name, IBinder binder) public void onServiceConnected(ComponentName name, IBinder binder)
@ -94,7 +101,6 @@ public class RemoteActivity extends Activity implements ServiceConnection, View.
IPlaybackService service = IPlaybackService.Stub.asInterface(binder); IPlaybackService service = IPlaybackService.Stub.asInterface(binder);
mCoverView.setPlaybackService(service); mCoverView.setPlaybackService(service);
try { try {
service.registerWatcher(mWatcher);
setState(service.getState()); setState(service.getState());
} catch (RemoteException e) { } catch (RemoteException e) {
} }
@ -136,23 +142,13 @@ public class RemoteActivity extends Activity implements ServiceConnection, View.
mPlayPauseButton.setImageResource(state == PlaybackService.STATE_PLAYING ? R.drawable.pause : R.drawable.play); mPlayPauseButton.setImageResource(state == PlaybackService.STATE_PLAYING ? R.drawable.pause : R.drawable.play);
} }
private IMusicPlayerWatcher mWatcher = new IMusicPlayerWatcher.Stub() { private BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void loaded() @Override
public void onReceive(Context context, Intent intent)
{ {
} String action = intent.getAction();
if (PlaybackService.EVENT_STATE_CHANGED.equals(action))
public void songChanged(Song playingSong) setState(intent.getIntExtra("newState", 0));
{
}
public void stateChanged(final int oldState, final int newState)
{
runOnUiThread(new Runnable() {
public void run()
{
setState(newState);
}
});
} }
}; };
} }