Fixed saving position in track, improvement with service binding, temporary new default album art.

This commit is contained in:
Karim Abou Zeid 2015-07-07 02:19:09 +02:00
commit cfa6ddaa2e
12 changed files with 140 additions and 61 deletions

View file

@ -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();
}
}

View file

@ -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:

View file

@ -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() {

View file

@ -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,

View file

@ -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() {

View file

@ -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;

View file

@ -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();
}
}

View file

@ -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

View file

@ -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;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 KiB