From 788e9fa52dc24f391a40450179873455a2f82ee2 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 13 Feb 2016 12:23:41 +0100 Subject: [PATCH] use a normal service instead of a bound service --- app/src/main/AndroidManifest.xml | 17 +- .../simplemobiletools/com/Constants.java | 11 ++ .../simplemobiletools/com/Events.java | 29 ++-- .../com/HeadsetPlugReceiver.java | 5 +- .../com/IncomingCallReceiver.java | 15 +- .../simplemobiletools/com/MainActivity.java | 162 ++++-------------- .../simplemobiletools/com/MusicService.java | 160 ++++++++--------- .../com/MyWidgetProvider.java | 33 ++-- .../com/RemoteControlReceiver.java | 11 +- app/src/main/res/layout/small_widget.xml | 12 +- 10 files changed, 194 insertions(+), 261 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c5d95c81..9038684b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ - + + + + + + + + + + + + + diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/Constants.java b/app/src/main/java/musicplayer/simplemobiletools/com/Constants.java index 110e5ceb..0a4f1259 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/Constants.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/Constants.java @@ -4,4 +4,15 @@ public class Constants { public static final String PREFS = "prefs"; public static final String WIDGET_BG_COLOR = "widget_bg_color"; public static final String WIDGET_TEXT_COLOR = "widget_text_color"; + public static final String SONG_POS = "song_position"; + + public static final String INIT = "musicplayer.simplemobiletools.com.action.INIT"; + public static final String PREVIOUS = "musicplayer.simplemobiletools.com.action.PREVIOUS"; + public static final String PAUSE = "musicplayer.simplemobiletools.com.action.PAUSE"; + public static final String PLAYPAUSE = "musicplayer.simplemobiletools.com.action.PLAYPAUSE"; + public static final String NEXT = "musicplayer.simplemobiletools.com.action.NEXT"; + public static final String STOP = "musicplayer.simplemobiletools.com.action.STOP"; + public static final String PLAYPOS = "musicplayer.simplemobiletools.com.action.PLAYPOS"; + public static final String CALL_START = "musicplayer.simplemobiletools.com.action.INCOMING_CALL_START"; + public static final String CALL_STOP = "musicplayer.simplemobiletools.com.action.INCOMING_CALL_STOP"; } diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/Events.java b/app/src/main/java/musicplayer/simplemobiletools/com/Events.java index 42e98d8c..a647af20 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/Events.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/Events.java @@ -1,21 +1,8 @@ package musicplayer.simplemobiletools.com; +import java.util.ArrayList; + public class Events { - public static class PreviousSong { - } - - public static class PlayPauseSong { - } - - public static class PauseSong { - } - - public static class NextSong { - } - - public static class StopSong { - } - public static class IncomingCallStart { } @@ -45,4 +32,16 @@ public class Events { return isPlaying; } } + + public static class PlaylistUpdated { + private ArrayList songs; + + PlaylistUpdated(ArrayList songs) { + this.songs = songs; + } + + public ArrayList getSongs() { + return songs; + } + } } diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/HeadsetPlugReceiver.java b/app/src/main/java/musicplayer/simplemobiletools/com/HeadsetPlugReceiver.java index 6d816846..511ae34e 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/HeadsetPlugReceiver.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/HeadsetPlugReceiver.java @@ -4,8 +4,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import com.squareup.otto.Bus; - public class HeadsetPlugReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { @@ -13,8 +11,7 @@ public class HeadsetPlugReceiver extends BroadcastReceiver { int state = intent.getIntExtra("state", -1); // we care only about the case where the headphone gets unplugged if (state == 0) { - final Bus bus = BusProvider.getInstance(); - bus.post(new Events.PauseSong()); + context.startService(new Intent(Constants.PAUSE)); } } } diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/IncomingCallReceiver.java b/app/src/main/java/musicplayer/simplemobiletools/com/IncomingCallReceiver.java index 9e3f6bc5..65559128 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/IncomingCallReceiver.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/IncomingCallReceiver.java @@ -1,20 +1,25 @@ package musicplayer.simplemobiletools.com; +import android.content.Context; +import android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; -import com.squareup.otto.Bus; - public class IncomingCallReceiver extends PhoneStateListener { + private Context cxt; + + public IncomingCallReceiver(Context context) { + cxt = context; + } + @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); - final Bus bus = BusProvider.getInstance(); if (state == TelephonyManager.CALL_STATE_RINGING) { - bus.post(new Events.IncomingCallStart()); + cxt.startService(new Intent(Constants.CALL_START)); } else if (state == TelephonyManager.CALL_STATE_IDLE || state == TelephonyManager.CALL_STATE_OFFHOOK) { - bus.post(new Events.IncomingCallStop()); + cxt.startService(new Intent(Constants.CALL_STOP)); } } } diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/MainActivity.java b/app/src/main/java/musicplayer/simplemobiletools/com/MainActivity.java index 6876c747..71730bc4 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/MainActivity.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/MainActivity.java @@ -1,25 +1,26 @@ package musicplayer.simplemobiletools.com; -import android.content.ComponentName; -import android.content.Context; import android.content.Intent; -import android.content.ServiceConnection; import android.os.Bundle; -import android.os.IBinder; import android.support.v7.app.AppCompatActivity; +import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; +import com.squareup.otto.Bus; +import com.squareup.otto.Subscribe; + +import java.util.ArrayList; + import butterknife.Bind; import butterknife.ButterKnife; import butterknife.OnClick; public class MainActivity extends AppCompatActivity { - private MusicService musicService; - private boolean isMusicBound; + private Bus bus; @Bind(R.id.playPauseBtn) ImageView playPauseBtn; @Bind(R.id.songs) ListView songsList; @@ -31,16 +32,15 @@ public class MainActivity extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); - - final Intent intent = new Intent(this, MusicService.class); - bindService(intent, musicConnection, Context.BIND_AUTO_CREATE); - startService(intent); + bus = BusProvider.getInstance(); + bus.register(this); + startService(new Intent(Constants.INIT)); } private void songPicked(int pos) { - musicService.setSong(pos, true); - updateSongInfo(musicService.getCurrSong()); - setPauseIcon(); + final Intent intent = new Intent(Constants.PLAYPOS); + intent.putExtra(Constants.SONG_POS, pos); + startService(intent); } private void updateSongInfo(Song song) { @@ -50,27 +50,8 @@ public class MainActivity extends AppCompatActivity { } } - private ServiceConnection musicConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - final MusicService.MyBinder binder = (MusicService.MyBinder) iBinder; - musicService = binder.getService(); - isMusicBound = true; - - updateSongInfo(musicService.getCurrSong()); - if (musicService.isPlaying()) - setPauseIcon(); - fillSongsListView(); - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - isMusicBound = false; - } - }; - - private void fillSongsListView() { - final SongAdapter adapter = new SongAdapter(this, musicService.getSongs()); + private void fillSongsListView(ArrayList songs) { + final SongAdapter adapter = new SongAdapter(this, songs); songsList.setAdapter(adapter); songsList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -80,127 +61,48 @@ public class MainActivity extends AppCompatActivity { }); } - @Override - protected void onResume() { - super.onResume(); - if (musicService != null) { - updateSongInfo(musicService.getCurrSong()); - - if (musicService.isPlaying()) { - setPauseIcon(); - } else { - setPlayIcon(); - } - } - } - @Override protected void onDestroy() { super.onDestroy(); - if (isMusicBound) { - isMusicBound = false; - unbindService(musicConnection); - } + bus.unregister(this); } @OnClick(R.id.previousBtn) public void previousClicked() { - if (isPlaylistEmpty()) - return; - - playPreviousSong(); + startService(new Intent(Constants.PREVIOUS)); } @OnClick(R.id.playPauseBtn) public void playPauseClicked() { - if (isPlaylistEmpty()) - return; - - resumePauseSong(); + startService(new Intent(Constants.PLAYPAUSE)); } @OnClick(R.id.nextBtn) public void nextClicked() { - if (isPlaylistEmpty()) - return; - - playNextSong(); + startService(new Intent(Constants.NEXT)); } @OnClick(R.id.stopBtn) public void stopClicked() { - if (isPlaylistEmpty()) - return; - - stopMusic(); + startService(new Intent(Constants.STOP)); } - public void stopMusic() { - if (musicService != null) { - musicService.stopSong(); - setPlayIcon(); - } + @Subscribe + public void songChangedEvent(Events.SongChanged event) { + updateSongInfo(event.getSong()); } - public void resumePauseSong() { - if (musicService == null) - return; + @Subscribe + public void songStateChanged(Events.SongStateChanged event) { + int id = R.mipmap.play; + if (event.getIsPlaying()) + id = R.mipmap.pause; - if (musicService.isPlaying()) { - pauseSong(); - } else { - resumeSong(); - } - - // in case we just launched the app and pressed play, also update the song and artist name - if (artistTV.getText().toString().trim().isEmpty()) - updateSongInfo(musicService.getCurrSong()); + playPauseBtn.setImageDrawable(getResources().getDrawable(id)); } - private void resumeSong() { - musicService.resumeSong(); - setPauseIcon(); - } - - private void pauseSong() { - if (musicService == null) - return; - - musicService.pauseSong(); - setPlayIcon(); - } - - private void playPreviousSong() { - if (musicService == null) - return; - - musicService.playPreviousSong(); - setPauseIcon(); - updateSongInfo(musicService.getCurrSong()); - } - - private void playNextSong() { - if (musicService == null) - return; - - musicService.playNextSong(); - updateSongInfo(musicService.getCurrSong()); - setPauseIcon(); - } - - private void setPlayIcon() { - playPauseBtn.setImageDrawable(getResources().getDrawable(R.mipmap.play)); - } - - private void setPauseIcon() { - playPauseBtn.setImageDrawable(getResources().getDrawable(R.mipmap.pause)); - } - - private boolean isPlaylistEmpty() { - if (musicService == null || musicService.getSongs().isEmpty()) { - Utils.showToast(this, R.string.playlist_empty); - return true; - } - return false; + @Subscribe + public void playlistUpdated(Events.PlaylistUpdated event) { + fillSongsListView(event.getSongs()); } } diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/MusicService.java b/app/src/main/java/musicplayer/simplemobiletools/com/MusicService.java index 26021747..37abe1da 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/MusicService.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/MusicService.java @@ -10,17 +10,14 @@ import android.database.Cursor; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; -import android.os.Binder; import android.os.IBinder; import android.os.PowerManager; import android.provider.MediaStore; -import android.support.annotation.Nullable; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import com.squareup.otto.Bus; -import com.squareup.otto.Subscribe; import java.io.IOException; import java.util.ArrayList; @@ -32,7 +29,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener { private static final String TAG = MusicService.class.getSimpleName(); private static final int MIN_DURATION_MS = 20000; - private final IBinder musicBind = new MyBinder(); private HeadsetPlugReceiver headsetPlugReceiver; private IncomingCallReceiver incomingCallReceiver; private ArrayList songs; @@ -55,11 +51,56 @@ public class MusicService extends Service getSortedSongs(); headsetPlugReceiver = new HeadsetPlugReceiver(); - incomingCallReceiver = new IncomingCallReceiver(); + incomingCallReceiver = new IncomingCallReceiver(this); wasPlayingAtCall = false; initMediaPlayer(); } + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + String action = intent.getAction(); + if (action != null) { + switch (action) { + case Constants.INIT: + bus.post(new Events.PlaylistUpdated(songs)); + bus.post(new Events.SongChanged(currSong)); + songStateChanged(isPlaying()); + break; + case Constants.PREVIOUS: + playPreviousSong(); + break; + case Constants.PAUSE: + pauseSong(); + break; + case Constants.PLAYPAUSE: + if (isPlaying()) + pauseSong(); + else + resumeSong(); + break; + case Constants.NEXT: + playNextSong(); + break; + case Constants.STOP: + stopSong(); + break; + case Constants.PLAYPOS: + playSong(intent); + break; + case Constants.CALL_START: + incomingCallStart(); + break; + case Constants.CALL_STOP: + incomingCallStop(); + break; + default: + break; + } + } + + return START_NOT_STICKY; + } + public void initMediaPlayer() { player = new MediaPlayer(); player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK); @@ -151,6 +192,10 @@ public class MusicService extends Service } public void resumeSong() { + if (songs.isEmpty()) { + fillPlaylist(); + } + if (songs.isEmpty()) return; @@ -182,10 +227,16 @@ public class MusicService extends Service player.seekTo(0); } + private void playSong(Intent intent) { + final int pos = intent.getIntExtra(Constants.SONG_POS, 0); + setSong(pos, true); + } + public void setSong(int songId, boolean addNewSong) { if (songs.isEmpty()) return; + final boolean wasPlaying = isPlaying(); if (player == null) initMediaPlayer(); @@ -204,32 +255,15 @@ public class MusicService extends Service player.prepareAsync(); bus.post(new Events.SongChanged(currSong)); - songStateChanged(true); + + if (!wasPlaying) { + songStateChanged(true); + } } - public Song getCurrSong() { - return currSong; - } - - @Nullable @Override public IBinder onBind(Intent intent) { - return musicBind; - } - - @Override - public boolean onUnbind(Intent intent) { - bus.post(new Events.SongChanged(null)); - songStateChanged(false); - - if (player != null && !player.isPlaying()) { - destroyPlayer(); - } - return false; - } - - public ArrayList getSongs() { - return songs; + return null; } @Override @@ -260,20 +294,32 @@ public class MusicService extends Service } private void destroyPlayer() { - player.stop(); - player.release(); - player = null; + if (player != null) { + player.stop(); + player.release(); + player = null; + } final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); telephonyManager.listen(incomingCallReceiver, PhoneStateListener.LISTEN_NONE); } - public class MyBinder extends Binder { - MusicService getService() { - return MusicService.this; + public void incomingCallStart() { + if (isPlaying()) { + wasPlayingAtCall = true; + pauseSong(); + } else { + wasPlayingAtCall = false; } } + public void incomingCallStop() { + if (wasPlayingAtCall) + resumeSong(); + + wasPlayingAtCall = false; + } + private void songStateChanged(boolean isPlaying) { bus.post(new Events.SongStateChanged(isPlaying)); @@ -287,54 +333,8 @@ public class MusicService extends Service try { unregisterReceiver(headsetPlugReceiver); } catch (IllegalArgumentException e) { + Log.e(TAG, "IllegalArgumentException " + e.getMessage()); } } } - - @Subscribe - public void previousSongEvent(Events.PreviousSong event) { - playPreviousSong(); - } - - @Subscribe - public void playPauseSongEvent(Events.PlayPauseSong event) { - if (isPlaying()) - pauseSong(); - else - resumeSong(); - } - - @Subscribe - public void nextSongEvent(Events.NextSong event) { - playNextSong(); - } - - @Subscribe - public void stopSongEvent(Events.StopSong event) { - stopSong(); - } - - @Subscribe - public void pauseSongEvent(Events.PauseSong event) { - // if the headset is unplugged, pause the song - pauseSong(); - } - - @Subscribe - public void incomingCallStart(Events.IncomingCallStart event) { - if (isPlaying()) { - wasPlayingAtCall = true; - pauseSong(); - } else { - wasPlayingAtCall = false; - } - } - - @Subscribe - public void incomingCallStop(Events.IncomingCallStop event) { - if (wasPlayingAtCall) - resumeSong(); - - wasPlayingAtCall = false; - } } diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/MyWidgetProvider.java b/app/src/main/java/musicplayer/simplemobiletools/com/MyWidgetProvider.java index ff1ab4fe..eaf3418f 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/MyWidgetProvider.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/MyWidgetProvider.java @@ -40,6 +40,7 @@ public class MyWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { initVariables(cxt); + super.onUpdate(context, appWidgetManager, appWidgetIds); } private void setupIntent(String action, int id) { @@ -52,15 +53,14 @@ public class MyWidgetProvider extends AppWidgetProvider { private void initVariables(Context context) { cxt = context; + intent = new Intent(cxt, MyWidgetProvider.class); final ComponentName component = new ComponentName(cxt, MyWidgetProvider.class); - widgetManager = AppWidgetManager.getInstance(cxt); widgetIds = widgetManager.getAppWidgetIds(component); - if (widgetIds.length == 0) - return; + for (int widgetId : widgetIds) { + remoteViews = getRemoteViews(widgetManager, cxt, widgetId); + } - remoteViews = getRemoteViews(widgetManager, cxt, widgetIds[0]); - intent = new Intent(cxt, MyWidgetProvider.class); setupViews(cxt); if (bus == null) { @@ -77,7 +77,7 @@ public class MyWidgetProvider extends AppWidgetProvider { public void songChangedEvent(Events.SongChanged event) { currSong = event.getSong(); updateSongInfo(); - updateWidget(); + updateWidgets(); } private void updateSongInfo() { @@ -99,7 +99,7 @@ public class MyWidgetProvider extends AppWidgetProvider { public void songStateChanged(Events.SongStateChanged event) { isPlaying = event.getIsPlaying(); updatePlayPauseButton(); - updateWidget(); + updateWidgets(); } private void updatePlayPauseButton() { @@ -111,8 +111,10 @@ public class MyWidgetProvider extends AppWidgetProvider { remoteViews.setImageViewBitmap(R.id.playPauseBtn, bmp); } - private void updateWidget() { - widgetManager.updateAppWidget(widgetIds, remoteViews); + private void updateWidgets() { + for (int widgetId : widgetIds) { + widgetManager.updateAppWidget(widgetId, remoteViews); + } } private void updateColors(Context context) { @@ -153,22 +155,23 @@ public class MyWidgetProvider extends AppWidgetProvider { @Override public void onReceive(Context context, Intent intent) { - if (remoteViews == null || widgetManager == null || widgetIds == null || bus == null) + if (remoteViews == null || widgetManager == null || bus == null) { initVariables(context); + } final String action = intent.getAction(); switch (action) { case PREVIOUS: - bus.post(new Events.PreviousSong()); + context.startService(new Intent(Constants.PREVIOUS)); break; case PLAYPAUSE: - bus.post(new Events.PlayPauseSong()); + context.startService(new Intent(Constants.PLAYPAUSE)); break; case NEXT: - bus.post(new Events.NextSong()); + context.startService(new Intent(Constants.NEXT)); break; case STOP: - bus.post(new Events.StopSong()); + context.startService(new Intent(Constants.STOP)); break; default: super.onReceive(context, intent); @@ -193,7 +196,7 @@ public class MyWidgetProvider extends AppWidgetProvider { setupButtons(); updateSongInfo(); updatePlayPauseButton(); - updateWidget(); + updateWidgets(); } @Override diff --git a/app/src/main/java/musicplayer/simplemobiletools/com/RemoteControlReceiver.java b/app/src/main/java/musicplayer/simplemobiletools/com/RemoteControlReceiver.java index c15f54a0..4262f9b5 100644 --- a/app/src/main/java/musicplayer/simplemobiletools/com/RemoteControlReceiver.java +++ b/app/src/main/java/musicplayer/simplemobiletools/com/RemoteControlReceiver.java @@ -6,15 +6,15 @@ import android.content.Intent; import android.os.Handler; import android.view.KeyEvent; -import com.squareup.otto.Bus; - public class RemoteControlReceiver extends BroadcastReceiver { private static final int MAX_CLICK_DURATION = 1000; private static int clicksCnt; + private static Context cxt; private static Handler handler = new Handler(); @Override public void onReceive(Context context, Intent intent) { + cxt = context; if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) { final KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); if (event.getAction() == KeyEvent.ACTION_UP && KeyEvent.KEYCODE_HEADSETHOOK == event.getKeyCode()) { @@ -36,13 +36,12 @@ public class RemoteControlReceiver extends BroadcastReceiver { if (clicksCnt == 0) return; - final Bus bus = BusProvider.getInstance(); if (clicksCnt == 1) { - bus.post(new Events.PlayPauseSong()); + cxt.startService(new Intent(Constants.PLAYPAUSE)); } else if (clicksCnt == 2) { - bus.post(new Events.NextSong()); + cxt.startService(new Intent(Constants.NEXT)); } else { - bus.post(new Events.PreviousSong()); + cxt.startService(new Intent(Constants.PREVIOUS)); } clicksCnt = 0; } diff --git a/app/src/main/res/layout/small_widget.xml b/app/src/main/res/layout/small_widget.xml index 6ea5486e..14d17763 100644 --- a/app/src/main/res/layout/small_widget.xml +++ b/app/src/main/res/layout/small_widget.xml @@ -1,9 +1,11 @@ - +