Fixed saving position in track, improvement with service binding, temporary new default album art.
This commit is contained in:
parent
1cccaad0f4
commit
cfa6ddaa2e
12 changed files with 140 additions and 61 deletions
|
|
@ -3,15 +3,12 @@ package com.kabouzeid.gramophone;
|
|||
import android.app.Application;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||
import com.nostra13.universalimageloader.utils.L;
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.ThreadEnforcer;
|
||||
|
||||
import org.jaudiotagger.tag.TagOptionSingleton;
|
||||
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
/**
|
||||
|
|
@ -24,14 +21,11 @@ public class App extends Application {
|
|||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (!BuildConfig.DEBUG) Fabric.with(this, new Crashlytics());
|
||||
|
||||
MusicPlayerRemote.startAndBindService(this);
|
||||
if (!BuildConfig.DEBUG) Fabric.with(this, new Crashlytics());
|
||||
|
||||
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build();
|
||||
ImageLoader.getInstance().init(config);
|
||||
L.writeLogs(false); // turns off UILs annoying LogCat output
|
||||
|
||||
TagOptionSingleton.getInstance().isAndroid();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import com.kabouzeid.gramophone.R;
|
|||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.service.MusicService;
|
||||
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
||||
import com.kabouzeid.gramophone.ui.activities.MainActivity;
|
||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
|
|
@ -117,7 +117,7 @@ public class WidgetMedium extends AppWidgetProvider {
|
|||
final ComponentName serviceName = new ComponentName(context, MusicService.class);
|
||||
switch (which) {
|
||||
case 0:
|
||||
action = new Intent(context, MusicControllerActivity.class);
|
||||
action = new Intent(context, MainActivity.class);
|
||||
pendingIntent = PendingIntent.getActivity(context, 0, action, 0);
|
||||
return pendingIntent;
|
||||
case 1:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.kabouzeid.gramophone.helper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
|
|
@ -15,6 +17,7 @@ import com.kabouzeid.gramophone.service.MusicService;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
|
|
@ -23,28 +26,75 @@ public class MusicPlayerRemote {
|
|||
|
||||
public static final String TAG = MusicPlayerRemote.class.getSimpleName();
|
||||
|
||||
public static final String SERVICE_BOUND = "com.kabouzeid.gramophone.SERVICE_BOUND";
|
||||
public static MusicService musicService;
|
||||
|
||||
private static MusicService musicService;
|
||||
private static final WeakHashMap<Context, ServiceBinder> mConnectionMap = new WeakHashMap<>();
|
||||
|
||||
private static final ServiceConnection musicConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
|
||||
musicService = binder.getService();
|
||||
musicService.sendBroadcast(new Intent(SERVICE_BOUND));
|
||||
public static ServiceToken bindToService(final Context context,
|
||||
final ServiceConnection callback) {
|
||||
Activity realActivity = ((Activity) context).getParent();
|
||||
if (realActivity == null) {
|
||||
realActivity = (Activity) context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
final ContextWrapper contextWrapper = new ContextWrapper(realActivity);
|
||||
contextWrapper.startService(new Intent(contextWrapper, MusicService.class));
|
||||
|
||||
final ServiceBinder binder = new ServiceBinder(callback);
|
||||
|
||||
if (contextWrapper.bindService(new Intent().setClass(contextWrapper, MusicService.class), binder, Context.BIND_AUTO_CREATE)) {
|
||||
mConnectionMap.put(contextWrapper, binder);
|
||||
return new ServiceToken(contextWrapper);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void unbindFromService(final ServiceToken token) {
|
||||
if (token == null) {
|
||||
return;
|
||||
}
|
||||
final ContextWrapper mContextWrapper = token.mWrappedContext;
|
||||
final ServiceBinder mBinder = mConnectionMap.remove(mContextWrapper);
|
||||
if (mBinder == null) {
|
||||
return;
|
||||
}
|
||||
mContextWrapper.unbindService(mBinder);
|
||||
if (mConnectionMap.isEmpty()) {
|
||||
musicService = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void startAndBindService(final Context context) {
|
||||
Intent musicServiceIntent = new Intent(context, MusicService.class);
|
||||
context.bindService(musicServiceIntent, musicConnection, Context.BIND_AUTO_CREATE);
|
||||
context.startService(musicServiceIntent);
|
||||
public static final class ServiceBinder implements ServiceConnection {
|
||||
private final ServiceConnection mCallback;
|
||||
|
||||
public ServiceBinder(final ServiceConnection callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName className, final IBinder service) {
|
||||
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
|
||||
musicService = binder.getService();
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceConnected(className, service);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName className) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceDisconnected(className);
|
||||
}
|
||||
musicService = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ServiceToken {
|
||||
public ContextWrapper mWrappedContext;
|
||||
|
||||
public ServiceToken(final ContextWrapper context) {
|
||||
mWrappedContext = context;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isServiceConnected() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ package com.kabouzeid.gramophone.helper;
|
|||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
|
@ -22,7 +21,7 @@ import android.widget.RemoteViews;
|
|||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.service.MusicService;
|
||||
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
||||
import com.kabouzeid.gramophone.ui.activities.MainActivity;
|
||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||
import com.kabouzeid.gramophone.util.PreferenceUtils;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
|
|
@ -122,11 +121,7 @@ public class PlayingNotificationHelper {
|
|||
}
|
||||
|
||||
private PendingIntent getOpenMusicControllerPendingIntent() {
|
||||
Intent result = new Intent(service, MusicControllerActivity.class);
|
||||
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(service);
|
||||
taskStackBuilder.addParentStack(MusicControllerActivity.class);
|
||||
taskStackBuilder.addNextIntent(result);
|
||||
return taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
return PendingIntent.getActivity(service, 0, new Intent(service, MainActivity.class), 0);
|
||||
}
|
||||
|
||||
private void setUpExpandedPlaybackActions() {
|
||||
|
|
@ -263,7 +258,7 @@ public class PlayingNotificationHelper {
|
|||
this.isPlaying = isPlaying;
|
||||
|
||||
if (notification == null) {
|
||||
return;
|
||||
updateNotification();
|
||||
}
|
||||
if (notificationLayout != null) {
|
||||
notificationLayout.setImageViewResource(R.id.action_play_pause,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ import java.util.List;
|
|||
* @author Karim Abou Zeid (kabouzeid), Andrew Neal
|
||||
*/
|
||||
public class MusicService extends Service {
|
||||
public static final String TAG = MusicService.class.getSimpleName();
|
||||
|
||||
public static final String PHONOGRAPH_PACKAGE_NAME = "com.kabouzeid.gramophone";
|
||||
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
|
||||
|
||||
|
|
@ -114,6 +116,7 @@ public class MusicService extends Service {
|
|||
private RecentlyPlayedStore recentlyPlayedStore;
|
||||
private SongPlayCountStore songPlayCountStore;
|
||||
private boolean notNotifiedMetaChangedForCurrentTrack;
|
||||
private boolean isServiceInUse;
|
||||
|
||||
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
|
|
@ -250,8 +253,7 @@ public class MusicService extends Service {
|
|||
stop();
|
||||
break;
|
||||
case ACTION_QUIT:
|
||||
quit();
|
||||
break;
|
||||
return quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -267,9 +269,24 @@ public class MusicService extends Service {
|
|||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
isServiceInUse = true;
|
||||
return musicBind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebind(Intent intent) {
|
||||
isServiceInUse = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnbind(Intent intent) {
|
||||
isServiceInUse = false;
|
||||
if (!isPlaying()) {
|
||||
stopSelf();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void unregisterReceiversAndRemoteControlClient() {
|
||||
if (receiversAndRemoteControlClientRegistered) {
|
||||
unregisterReceiver(becomingNoisyReceiver);
|
||||
|
|
@ -282,12 +299,18 @@ public class MusicService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
private void quit() {
|
||||
private int quit() {
|
||||
unregisterReceiversAndRemoteControlClient();
|
||||
closeAudioEffectSession();
|
||||
stop();
|
||||
pause();
|
||||
playingNotificationHelper.killNotification();
|
||||
stopSelf();
|
||||
|
||||
if (isServiceInUse) {
|
||||
return START_STICKY;
|
||||
} else {
|
||||
closeAudioEffectSession();
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseResources() {
|
||||
|
|
|
|||
|
|
@ -111,16 +111,7 @@ public class AlbumDetailActivity extends AbsFabActivity implements PaletteColorH
|
|||
setNavigationBarColor(DialogUtils.resolveColor(this, R.attr.default_bar_color));
|
||||
}
|
||||
|
||||
Bundle intentExtras = getIntent().getExtras();
|
||||
int albumId = -1;
|
||||
if (intentExtras != null) {
|
||||
albumId = intentExtras.getInt(EXTRA_ALBUM_ID);
|
||||
}
|
||||
album = AlbumLoader.getAlbum(this, albumId);
|
||||
if (album.id == -1) {
|
||||
finish();
|
||||
}
|
||||
|
||||
getAlbumFromIntentExtras();
|
||||
setUpObservableListViewParams();
|
||||
setUpToolBar();
|
||||
setUpViews();
|
||||
|
|
@ -180,6 +171,15 @@ public class AlbumDetailActivity extends AbsFabActivity implements PaletteColorH
|
|||
}
|
||||
};
|
||||
|
||||
private void getAlbumFromIntentExtras() {
|
||||
Bundle intentExtras = getIntent().getExtras();
|
||||
final int albumId = intentExtras.getInt(EXTRA_ALBUM_ID);
|
||||
album = AlbumLoader.getAlbum(this, albumId);
|
||||
if (album.id == -1) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ public class ArtistDetailActivity extends AbsFabActivity implements PaletteColor
|
|||
|
||||
lastFMRestClient = new LastFMRestClient(this);
|
||||
|
||||
getIntentExtras();
|
||||
getArtistFromIntentExtras();
|
||||
initViews();
|
||||
setUpObservableListViewParams();
|
||||
setUpViews();
|
||||
|
|
@ -430,11 +430,11 @@ public class ArtistDetailActivity extends AbsFabActivity implements PaletteColor
|
|||
notifyTaskColorChange(toolbarColor);
|
||||
}
|
||||
|
||||
private void getIntentExtras() {
|
||||
private void getArtistFromIntentExtras() {
|
||||
Bundle intentExtras = getIntent().getExtras();
|
||||
final int artistId = intentExtras.getInt(EXTRA_ARTIST_ID);
|
||||
artist = ArtistLoader.getArtist(this, artistId);
|
||||
if (artist == null) {
|
||||
if (artist.id == -1) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import butterknife.Optional;
|
|||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public abstract class AbsFabActivity extends AbsPlaybackStatusActivity {
|
||||
public abstract class AbsFabActivity extends AbsPlaybackControlActivity {
|
||||
public static final String TAG = AbsFabActivity.class.getSimpleName();
|
||||
|
||||
@Optional
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package com.kabouzeid.gramophone.ui.activities.base;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||
import com.kabouzeid.gramophone.service.MusicService;
|
||||
|
|
@ -13,7 +17,8 @@ import java.lang.ref.WeakReference;
|
|||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public abstract class AbsPlaybackStatusActivity extends AbsBaseActivity {
|
||||
public abstract class AbsPlaybackControlActivity extends AbsBaseActivity {
|
||||
private MusicPlayerRemote.ServiceToken serviceToken;
|
||||
private PlaybackStatusReceiver playbackStatusReceiver;
|
||||
|
||||
public void onPlayingMetaChanged() {
|
||||
|
|
@ -36,23 +41,32 @@ public abstract class AbsPlaybackStatusActivity extends AbsBaseActivity {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
serviceToken = MusicPlayerRemote.bindToService(this, new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
AbsPlaybackControlActivity.this.onServiceConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
|
||||
}
|
||||
});
|
||||
playbackStatusReceiver = new PlaybackStatusReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
playbackStatusReceiver = new PlaybackStatusReceiver(this);
|
||||
|
||||
// ensures that onServiceConnected() is called even if the service is already connected and wont sent the Intent again.
|
||||
if (MusicPlayerRemote.isServiceConnected()) {
|
||||
onServiceConnected();
|
||||
}
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(MusicService.PLAY_STATE_CHANGED);
|
||||
filter.addAction(MusicService.SHUFFLE_MODE_CHANGED);
|
||||
filter.addAction(MusicService.REPEAT_MODE_CHANGED);
|
||||
filter.addAction(MusicService.META_CHANGED);
|
||||
filter.addAction(MusicPlayerRemote.SERVICE_BOUND);
|
||||
|
||||
registerReceiver(playbackStatusReceiver, filter);
|
||||
}
|
||||
|
|
@ -66,11 +80,17 @@ public abstract class AbsPlaybackStatusActivity extends AbsBaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
MusicPlayerRemote.unbindFromService(serviceToken);
|
||||
}
|
||||
|
||||
private static final class PlaybackStatusReceiver extends BroadcastReceiver {
|
||||
|
||||
private final WeakReference<AbsPlaybackStatusActivity> reference;
|
||||
private final WeakReference<AbsPlaybackControlActivity> reference;
|
||||
|
||||
public PlaybackStatusReceiver(final AbsPlaybackStatusActivity activity) {
|
||||
public PlaybackStatusReceiver(final AbsPlaybackControlActivity activity) {
|
||||
reference = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
|
|
@ -90,9 +110,6 @@ public abstract class AbsPlaybackStatusActivity extends AbsBaseActivity {
|
|||
case MusicService.SHUFFLE_MODE_CHANGED:
|
||||
reference.get().onShuffleModeChanged();
|
||||
break;
|
||||
case MusicPlayerRemote.SERVICE_BOUND:
|
||||
reference.get().onServiceConnected();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue