From 34326718adda9780426145c65af9a2bf31fd8b26 Mon Sep 17 00:00:00 2001 From: Christopher Eby Date: Sun, 18 Sep 2011 15:36:13 -0500 Subject: [PATCH] Move service-related code out of ContextApplication --- src/org/kreed/vanilla/ContextApplication.java | 115 ------------------ src/org/kreed/vanilla/CoverView.java | 5 +- src/org/kreed/vanilla/FourLongWidget.java | 4 +- src/org/kreed/vanilla/FourSquareWidget.java | 4 +- .../kreed/vanilla/FullPlaybackActivity.java | 4 +- src/org/kreed/vanilla/MediaUtils.java | 8 +- src/org/kreed/vanilla/OneCellWidget.java | 4 +- src/org/kreed/vanilla/PlaybackActivity.java | 33 ++--- src/org/kreed/vanilla/PlaybackService.java | 94 ++++++++++++-- src/org/kreed/vanilla/SongSelector.java | 8 +- 10 files changed, 124 insertions(+), 155 deletions(-) diff --git a/src/org/kreed/vanilla/ContextApplication.java b/src/org/kreed/vanilla/ContextApplication.java index 5c97d715..e04e2aeb 100644 --- a/src/org/kreed/vanilla/ContextApplication.java +++ b/src/org/kreed/vanilla/ContextApplication.java @@ -22,23 +22,16 @@ package org.kreed.vanilla; -import java.util.ArrayList; import java.util.Random; -import android.app.Activity; import android.app.Application; import android.content.Context; -import android.content.Intent; -import android.database.ContentObserver; -import android.provider.MediaStore; /** * Subclass of Application that provides various static utility functions */ public class ContextApplication extends Application { private static ContextApplication mInstance; - public static ArrayList mActivities; - private static PlaybackService mService; private static Random mRandom; public ContextApplication() @@ -46,30 +39,6 @@ public class ContextApplication extends Application { mInstance = this; } - @Override - public void onCreate() - { - getContentResolver().registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mObserver); - } - - private ContentObserver mObserver = new ContentObserver(null) { - @Override - public void onChange(boolean selfChange) - { - Song.onMediaChange(); - if (mService != null) - mService.onMediaChange(); - ArrayList list = mActivities; - if (list != null) { - for (int i = list.size(); --i != -1; ) { - Activity activity = list.get(i); - if (activity instanceof PlaybackActivity) - ((PlaybackActivity)activity).onMediaChange(); - } - } - } - }; - /** * Returns a shared, application-wide Random instance. */ @@ -87,88 +56,4 @@ public class ContextApplication extends Application { { return mInstance; } - - /** - * Return the PlaybackService instance, creating one if needed. - */ - public static PlaybackService getService() - { - if (mService == null) { - mInstance.startService(new Intent(mInstance, PlaybackService.class)); - while (mService == null) { - try { - synchronized (mInstance) { - mInstance.wait(); - } - } catch (InterruptedException e) { - } - } - } - - return mService; - } - - /** - * Returns whether a PlaybackService instance is active. - */ - public static boolean hasService() - { - return mService != null; - } - - /** - * Set the PlaybackService instance to service and notify all - * clients waiting for an instance. - */ - public static void setService(PlaybackService service) - { - mService = service; - synchronized (mInstance) { - mInstance.notifyAll(); - } - } - - /** - * Add an Activity to the list of Activities. - * - * @param activity The Activity to be added - */ - public static void addActivity(Activity activity) - { - if (mActivities == null) - mActivities = new ArrayList(); - mActivities.add(activity); - } - - /** - * Remove an Activity from the list of Activities. - * - * @param activity The Activity to be removed - */ - public static void removeActivity(Activity activity) - { - if (mActivities != null) - mActivities.remove(activity); - } - - /** - * Send a broadcast to all PlaybackActivities that have been added with - * addActivity and then with Context.sendBroadcast. - * - * @param intent The intent to be sent as a broadcast - */ - public static void broadcast(Intent intent) - { - ArrayList list = mActivities; - if (list != null) { - for (int i = list.size(); --i != -1; ) { - Activity activity = list.get(i); - if (activity instanceof PlaybackActivity) - ((PlaybackActivity)activity).receive(intent); - } - } - - if (mInstance != null) - mInstance.sendBroadcast(intent); - } } diff --git a/src/org/kreed/vanilla/CoverView.java b/src/org/kreed/vanilla/CoverView.java index 83e6f789..15ccdf88 100644 --- a/src/org/kreed/vanilla/CoverView.java +++ b/src/org/kreed/vanilla/CoverView.java @@ -347,10 +347,11 @@ public final class CoverView extends View implements Handler.Callback { /** * Query all songs. Must be called on the UI thread. + * + * @param service Service to query from. */ - public void querySongs() + public void querySongs(PlaybackService service) { - PlaybackService service = ContextApplication.getService(); for (int i = STORE_SIZE; --i != -1; ) setSong(i, service.getSong(i - STORE_SIZE / 2)); resetScroll(); diff --git a/src/org/kreed/vanilla/FourLongWidget.java b/src/org/kreed/vanilla/FourLongWidget.java index 3dab45e6..9d255146 100644 --- a/src/org/kreed/vanilla/FourLongWidget.java +++ b/src/org/kreed/vanilla/FourLongWidget.java @@ -56,8 +56,8 @@ public class FourLongWidget extends AppWidgetProvider { Song song = null; int state = 0; - if (ContextApplication.hasService()) { - PlaybackService service = ContextApplication.getService(); + if (PlaybackService.hasInstance()) { + PlaybackService service = PlaybackService.get(context); song = service.getSong(0); state = service.getState(); } diff --git a/src/org/kreed/vanilla/FourSquareWidget.java b/src/org/kreed/vanilla/FourSquareWidget.java index 6e0e03d5..7dc41c5e 100644 --- a/src/org/kreed/vanilla/FourSquareWidget.java +++ b/src/org/kreed/vanilla/FourSquareWidget.java @@ -56,8 +56,8 @@ public class FourSquareWidget extends AppWidgetProvider { Song song = null; int state = 0; - if (ContextApplication.hasService()) { - PlaybackService service = ContextApplication.getService(); + if (PlaybackService.hasInstance()) { + PlaybackService service = PlaybackService.get(context); song = service.getSong(0); state = service.getState(); } diff --git a/src/org/kreed/vanilla/FullPlaybackActivity.java b/src/org/kreed/vanilla/FullPlaybackActivity.java index 478c69c4..3c2360e0 100644 --- a/src/org/kreed/vanilla/FullPlaybackActivity.java +++ b/src/org/kreed/vanilla/FullPlaybackActivity.java @@ -318,7 +318,7 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On */ private void updateProgress() { - int position = ContextApplication.hasService() ? ContextApplication.getService().getPosition() : 0; + int position = PlaybackService.hasInstance() ? PlaybackService.get(this).getPosition() : 0; if (!mSeekBarTracking) mSeekBar.setProgress(mDuration == 0 ? 0 : (int)(1000 * position / mDuration)); @@ -409,7 +409,7 @@ public class FullPlaybackActivity extends PlaybackActivity implements SeekBar.On public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) - ContextApplication.getService().seekToProgress(progress); + PlaybackService.get(this).seekToProgress(progress); } public void onStartTrackingTouch(SeekBar seekBar) diff --git a/src/org/kreed/vanilla/MediaUtils.java b/src/org/kreed/vanilla/MediaUtils.java index ed1df8ae..2076adea 100644 --- a/src/org/kreed/vanilla/MediaUtils.java +++ b/src/org/kreed/vanilla/MediaUtils.java @@ -26,6 +26,7 @@ import java.io.File; import java.util.Random; import android.content.ContentResolver; +import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.provider.MediaStore; @@ -192,20 +193,21 @@ public class MediaUtils { /** * Delete all the songs in the given media set. * + * @param context A context to use. * @param type One of the TYPE_* constants, excluding playlists. * @param id The MediaStore id of the media to delete. * @return The number of songs deleted. */ - public static int deleteMedia(int type, long id) + public static int deleteMedia(Context context, int type, long id) { int count = 0; - ContentResolver resolver = ContextApplication.getContext().getContentResolver(); + ContentResolver resolver = context.getContentResolver(); String[] projection = new String [] { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA }; Cursor cursor = getMediaCursor(type, id, projection, null); if (cursor != null) { - PlaybackService service = ContextApplication.hasService() ? ContextApplication.getService() : null; + PlaybackService service = PlaybackService.hasInstance() ? PlaybackService.get(context) : null; while (cursor.moveToNext()) { if (new File(cursor.getString(1)).delete()) { diff --git a/src/org/kreed/vanilla/OneCellWidget.java b/src/org/kreed/vanilla/OneCellWidget.java index 9393b3b2..efc08746 100644 --- a/src/org/kreed/vanilla/OneCellWidget.java +++ b/src/org/kreed/vanilla/OneCellWidget.java @@ -57,8 +57,8 @@ public class OneCellWidget extends AppWidgetProvider { Song song = null; int state = 0; - if (ContextApplication.hasService()) { - PlaybackService service = ContextApplication.getService(); + if (PlaybackService.hasInstance()) { + PlaybackService service = PlaybackService.get(context); song = service.getSong(0); state = service.getState(); } diff --git a/src/org/kreed/vanilla/PlaybackActivity.java b/src/org/kreed/vanilla/PlaybackActivity.java index 91b93f41..b0b00d3c 100644 --- a/src/org/kreed/vanilla/PlaybackActivity.java +++ b/src/org/kreed/vanilla/PlaybackActivity.java @@ -70,7 +70,8 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View public void onCreate(Bundle state) { super.onCreate(state); - ContextApplication.addActivity(this); + + PlaybackService.addActivity(this); setVolumeControlStream(AudioManager.STREAM_MUSIC); @@ -88,9 +89,9 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View @Override public void onDestroy() { - super.onDestroy(); - ContextApplication.removeActivity(this); + PlaybackService.removeActivity(this); mLooper.quit(); + super.onDestroy(); } @Override @@ -98,7 +99,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View { super.onStart(); - if (ContextApplication.hasService()) + if (PlaybackService.hasInstance()) onServiceReady(); else startService(new Intent(this, PlaybackService.class)); @@ -108,8 +109,8 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View public void onResume() { super.onResume(); - if (ContextApplication.hasService()) { - PlaybackService service = ContextApplication.getService(); + if (PlaybackService.hasInstance()) { + PlaybackService service = PlaybackService.get(this); service.userActionTriggered(); MediaButtonHandler buttons = MediaButtonHandler.getInstance(); @@ -148,17 +149,17 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View public void nextSong() { - setSong(ContextApplication.getService().nextSong()); + setSong(PlaybackService.get(this).nextSong()); } public void previousSong() { - setSong(ContextApplication.getService().previousSong()); + setSong(PlaybackService.get(this).previousSong()); } public void playPause() { - PlaybackService service = ContextApplication.getService(); + PlaybackService service = PlaybackService.get(this); int state = service.playPause(); if ((state & PlaybackService.FLAG_ERROR) != 0) Toast.makeText(this, service.getErrorMessage(), Toast.LENGTH_LONG).show(); @@ -214,7 +215,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View */ protected void onServiceReady() { - PlaybackService service = ContextApplication.getService(); + PlaybackService service = PlaybackService.get(this); setSong(service.getSong(0)); setState(service.getState()); } @@ -227,7 +228,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View protected void onSongChange(Song song) { if (mCoverView != null) - mCoverView.querySongs(); + mCoverView.querySongs(PlaybackService.get(this)); } protected void setSong(final Song song) @@ -339,7 +340,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View */ public void toggleShuffle() { - int state = ContextApplication.getService().toggleShuffle(); + int state = PlaybackService.get(this).toggleShuffle(); int res = (state & PlaybackService.FLAG_SHUFFLE) == 0 ? R.string.shuffle_disabling : R.string.shuffle_enabling; Toast.makeText(this, res, Toast.LENGTH_SHORT).show(); setState(state); @@ -350,7 +351,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View */ public void toggleRepeat() { - int state = ContextApplication.getService().toggleRepeat(); + int state = PlaybackService.get(this).toggleRepeat(); int res = (state & PlaybackService.FLAG_REPEAT) == 0 ? R.string.repeat_disabling : R.string.repeat_enabling; Toast.makeText(this, res, Toast.LENGTH_SHORT).show(); setState(state); @@ -361,7 +362,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View */ public void toggleRandom() { - int state = ContextApplication.getService().toggleRandom(); + int state = PlaybackService.get(this).toggleRandom(); int res = (state & PlaybackService.FLAG_RANDOM) == 0 ? R.string.random_disabling : R.string.random_enabling; Toast.makeText(this, res, Toast.LENGTH_SHORT).show(); setState(state); @@ -377,7 +378,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View public void enqueue(int type) { - int count = ContextApplication.getService().enqueueFromCurrent(type); + int count = PlaybackService.get(this).enqueueFromCurrent(type); String text = getResources().getQuantityString(R.plurals.enqueued, count, count); Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } @@ -418,7 +419,7 @@ public class PlaybackActivity extends Activity implements Handler.Callback, View enqueue(MediaUtils.TYPE_GENRE); break; case ACTION_CLEAR_QUEUE: - ContextApplication.getService().clearQueue(); + PlaybackService.get(this).clearQueue(); Toast.makeText(this, R.string.queue_cleared, Toast.LENGTH_SHORT).show(); break; default: diff --git a/src/org/kreed/vanilla/PlaybackService.java b/src/org/kreed/vanilla/PlaybackService.java index d1e8d0bc..96feab80 100644 --- a/src/org/kreed/vanilla/PlaybackService.java +++ b/src/org/kreed/vanilla/PlaybackService.java @@ -25,7 +25,6 @@ package org.kreed.vanilla; import java.io.IOException; import java.util.ArrayList; -import android.app.Activity; import android.app.NotificationManager; import android.app.Service; import android.appwidget.AppWidgetManager; @@ -34,6 +33,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.database.ContentObserver; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Handler; @@ -43,6 +43,7 @@ import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.preference.PreferenceManager; +import android.provider.MediaStore; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; @@ -135,6 +136,10 @@ public final class PlaybackService extends Service implements Handler.Callback, public static final int WHEN_PLAYING = 1; public static final int ALWAYS = 2; + private static Object sWait = new Object(); + private static PlaybackService sInstance; + private static ArrayList sActivities = new ArrayList(); + boolean mHeadsetPause; private boolean mScrobble; private int mNotificationMode; @@ -227,7 +232,10 @@ public final class PlaybackService extends Service implements Handler.Callback, updateState(state); setCurrentSong(0); - ContextApplication.setService(this); + sInstance = this; + synchronized (sWait) { + sWait.notifyAll(); + } } @Override @@ -272,7 +280,7 @@ public final class PlaybackService extends Service implements Handler.Callback, @Override public void onDestroy() { - ContextApplication.setService(null); + sInstance = null; mLooper.quit(); @@ -340,8 +348,8 @@ public final class PlaybackService extends Service implements Handler.Callback, } else if ("disable_cover_art".equals(key)) { Song.mDisableCoverArt = settings.getBoolean("disable_cover_art", false); } else if ("display_mode".equals(key)) { - ArrayList activities = ContextApplication.mActivities; - for (Activity activity : activities) { + ArrayList activities = sActivities; + for (PlaybackActivity activity : activities) { if (activity instanceof FullPlaybackActivity) activity.finish(); } @@ -446,6 +454,13 @@ public final class PlaybackService extends Service implements Handler.Callback, } } + private void broadcast(Intent intent) + { + ArrayList list = sActivities; + for (int i = list.size(); --i != -1; ) + list.get(i).receive(intent); + } + private void broadcastChange(int state, Song song, long uptime) { Intent intent = new Intent(EVENT_CHANGED); @@ -454,7 +469,7 @@ public final class PlaybackService extends Service implements Handler.Callback, if (song != null) intent.putExtra("song", song); intent.putExtra("time", uptime); - ContextApplication.broadcast(intent); + broadcast(intent); updateWidgets(); @@ -745,6 +760,11 @@ public final class PlaybackService extends Service implements Handler.Callback, } else { setFlag(FLAG_NO_MEDIA); } + + ArrayList list = sActivities; + for (int i = list.size(); --i != -1; ) + list.get(i).onMediaChange(); + } public void onSharedPreferenceChanged(SharedPreferences settings, String key) @@ -816,6 +836,8 @@ public final class PlaybackService extends Service implements Handler.Callback, mCallListener = new InCallListener(); TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); telephonyManager.listen(mCallListener, PhoneStateListener.LISTEN_CALL_STATE); + + getContentResolver().registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mObserver); break; case IDLE_TIMEOUT: if ((mState & FLAG_PLAYING) != 0) @@ -839,7 +861,7 @@ public final class PlaybackService extends Service implements Handler.Callback, processNewState(message.arg1, message.arg2); break; case BROADCAST: - ContextApplication.broadcast((Intent)message.obj); + broadcast((Intent)message.obj); break; case BROADCAST_CHANGE: broadcastChange(message.arg1, (Song)message.obj, message.getWhen()); @@ -1028,4 +1050,62 @@ public final class PlaybackService extends Service implements Handler.Callback, mHandler.removeMessages(SAVE_STATE); mHandler.sendEmptyMessageDelayed(SAVE_STATE, 5000); } + + private ContentObserver mObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) + { + Song.onMediaChange(); + onMediaChange(); + } + }; + + /** + * Return the PlaybackService instance, creating one if needed. + */ + public static PlaybackService get(Context context) + { + if (sInstance == null) { + context.startService(new Intent(context, PlaybackService.class)); + + while (sInstance == null) { + try { + synchronized (sWait) { + sWait.wait(); + } + } catch (InterruptedException e) { + } + } + } + + return sInstance; + } + + /** + * Returns true if a PlaybackService instance is active. + */ + public static boolean hasInstance() + { + return sInstance != null; + } + + /** + * Add an Activity to the registered PlaybackActivities. + * + * @param activity The Activity to be added + */ + public static void addActivity(PlaybackActivity activity) + { + sActivities.add(activity); + } + + /** + * Remove an Activity from the registered PlaybackActivities + * + * @param activity The Activity to be removed + */ + public static void removeActivity(PlaybackActivity activity) + { + sActivities.remove(activity); + } } diff --git a/src/org/kreed/vanilla/SongSelector.java b/src/org/kreed/vanilla/SongSelector.java index 0d902142..6b98f18d 100644 --- a/src/org/kreed/vanilla/SongSelector.java +++ b/src/org/kreed/vanilla/SongSelector.java @@ -167,8 +167,8 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem if (mSearchBoxVisible) mControls.setVisibility(View.GONE); - if (ContextApplication.hasService()) { - PlaybackService service = ContextApplication.getService(); + if (PlaybackService.hasInstance()) { + PlaybackService service = PlaybackService.get(this); // Force the state to be updated, even if PlaybackActivity has // already loaded it. This is needed to set the proper image // for the play/pause button. @@ -243,7 +243,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem */ private void pickSongs(MediaAdapter.MediaView view, int action) { - PlaybackService service = ContextApplication.getService(); + PlaybackService service = PlaybackService.get(this); int type = view.getMediaType(); long id = view.getMediaId(); int mode; @@ -493,7 +493,7 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem String message = getResources().getString(R.string.playlist_deleted, title); Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } else { - int count = MediaUtils.deleteMedia(type, id); + int count = MediaUtils.deleteMedia(this, type, id); String message = getResources().getQuantityString(R.plurals.deleted, count, count); Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); }