Amend last commit. Added new drawables and removed obsolete drawables and layouts.
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.kabouzeid.gramophone.helper;
|
||||||
|
|
||||||
|
import android.media.RemoteControlClient;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
|
import android.support.v4.media.session.PlaybackStateCompat;
|
||||||
|
|
||||||
|
public class MediaSessionHelper {
|
||||||
|
|
||||||
|
public static void applyState(MediaSessionCompat session, PlaybackStateCompat playbackState) {
|
||||||
|
session.setPlaybackState(playbackState);
|
||||||
|
ensureTransportControls(session, playbackState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ensureTransportControls(MediaSessionCompat session, PlaybackStateCompat playbackState) {
|
||||||
|
long actions = playbackState.getActions();
|
||||||
|
Object rccObj = session.getRemoteControlClient();
|
||||||
|
|
||||||
|
if (actions != 0
|
||||||
|
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
|
||||||
|
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
|
||||||
|
&& rccObj != null) {
|
||||||
|
|
||||||
|
int transportControls = 0;
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_REWIND) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_REWIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_PLAY) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_PAUSE) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PAUSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_STOP) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_SEEK_TO) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((actions & PlaybackStateCompat.ACTION_SET_RATING) != 0) {
|
||||||
|
transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_RATING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((RemoteControlClient) rccObj).setTransportControlFlags(transportControls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,16 +5,15 @@ package com.kabouzeid.gramophone.helper;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.TaskStackBuilder;
|
import android.app.TaskStackBuilder;
|
||||||
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.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v7.app.NotificationCompat;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.RemoteViews;
|
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
|
@ -22,192 +21,101 @@ import com.kabouzeid.gramophone.service.MusicService;
|
||||||
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
||||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
|
||||||
import com.nostra13.universalimageloader.core.assist.ImageSize;
|
|
||||||
import com.nostra13.universalimageloader.core.assist.ViewScaleType;
|
|
||||||
import com.nostra13.universalimageloader.core.imageaware.NonViewAware;
|
|
||||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
|
||||||
|
|
||||||
public class PlayingNotificationHelper {
|
public class PlayingNotificationHelper {
|
||||||
|
|
||||||
public static final String TAG = PlayingNotificationHelper.class.getSimpleName();
|
public static final String TAG = PlayingNotificationHelper.class.getSimpleName();
|
||||||
public static final int NOTIFICATION_ID = 1337;
|
|
||||||
|
|
||||||
private final MusicService service;
|
public static Notification buildNotification(final Context context, MediaSessionCompat.Token sessionToken, final Song song, final boolean isPlaying) {
|
||||||
|
|
||||||
private final NotificationManager notificationManager;
|
NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle()
|
||||||
private Notification notification = null;
|
.setMediaSession(sessionToken)
|
||||||
|
.setShowActionsInCompactView(0, 1, 2);
|
||||||
|
|
||||||
private RemoteViews notificationLayout;
|
style.setShowCancelButton(true);
|
||||||
private RemoteViews notificationLayoutExpanded;
|
style.setCancelButtonIntent(retrievePlaybackAction(context, 3));
|
||||||
|
|
||||||
private Song currentSong;
|
Bitmap albumArt = ImageLoader.getInstance().loadImageSync(MusicUtil.getAlbumArtUri(song.albumId).toString());
|
||||||
private String currentAlbumArtUri;
|
if (albumArt == null) {
|
||||||
|
albumArt = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_album_art);
|
||||||
|
}
|
||||||
|
|
||||||
public PlayingNotificationHelper(final MusicService service) {
|
return new NotificationCompat.Builder(context)
|
||||||
this.service = service;
|
|
||||||
notificationManager = (NotificationManager) service
|
|
||||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void buildNotification(final Song song, final boolean isPlaying) {
|
|
||||||
currentSong = song;
|
|
||||||
notificationLayout = new RemoteViews(service.getPackageName(),
|
|
||||||
R.layout.notification_playing);
|
|
||||||
notificationLayoutExpanded = new RemoteViews(service.getPackageName(),
|
|
||||||
R.layout.notification_playing_expanded);
|
|
||||||
|
|
||||||
notification = new NotificationCompat.Builder(service)
|
|
||||||
.setSmallIcon(R.drawable.ic_notification)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setContentIntent(getOpenMusicControllerPendingIntent())
|
.setLargeIcon(albumArt)
|
||||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
.setContentIntent(getOpenMusicControllerPendingIntent(context))
|
||||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
.setContentTitle(song.title)
|
||||||
|
.setContentText(song.artistName)
|
||||||
|
.setSubText(song.albumName)
|
||||||
|
.setWhen(0)
|
||||||
|
.setShowWhen(false)
|
||||||
|
.setStyle(style)
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
.setContent(notificationLayout)
|
|
||||||
.setStyle(new NotificationCompat.MediaStyle())
|
.addAction(R.drawable.ic_skip_previous_white_36dp,
|
||||||
|
"",
|
||||||
|
retrievePlaybackAction(context, 2))
|
||||||
|
|
||||||
|
.addAction(isPlaying ? R.drawable.ic_pause_white_36dp : R.drawable.ic_play_arrow_white_36dp,
|
||||||
|
"",
|
||||||
|
retrievePlaybackAction(context, 0))
|
||||||
|
|
||||||
|
.addAction(R.drawable.ic_skip_next_white_36dp,
|
||||||
|
"",
|
||||||
|
retrievePlaybackAction(context, 1))
|
||||||
|
|
||||||
|
.setOnlyAlertOnce(true)
|
||||||
.build();
|
.build();
|
||||||
notification.bigContentView = notificationLayoutExpanded;
|
|
||||||
|
|
||||||
setUpCollapsedLayout();
|
|
||||||
setUpExpandedLayout();
|
|
||||||
loadAlbumArt();
|
|
||||||
setUpPlaybackActions(isPlaying);
|
|
||||||
setUpExpandedPlaybackActions(isPlaying);
|
|
||||||
|
|
||||||
service.startForeground(NOTIFICATION_ID, notification);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PendingIntent getOpenMusicControllerPendingIntent() {
|
private static PendingIntent getOpenMusicControllerPendingIntent(final Context context) {
|
||||||
Intent result = new Intent(service, MusicControllerActivity.class);
|
Intent result = new Intent(context, MusicControllerActivity.class);
|
||||||
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(service);
|
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
|
||||||
taskStackBuilder.addParentStack(MusicControllerActivity.class);
|
taskStackBuilder.addParentStack(MusicControllerActivity.class);
|
||||||
taskStackBuilder.addNextIntent(result);
|
taskStackBuilder.addNextIntent(result);
|
||||||
return taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
return taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpExpandedPlaybackActions(boolean isPlaying) {
|
private static PendingIntent retrievePlaybackAction(final Context context, final int which) {
|
||||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_toggle_play_pause,
|
String actionString = null;
|
||||||
retrievePlaybackActions(1));
|
|
||||||
|
|
||||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_next,
|
|
||||||
retrievePlaybackActions(2));
|
|
||||||
|
|
||||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_prev,
|
|
||||||
retrievePlaybackActions(3));
|
|
||||||
|
|
||||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_quit,
|
|
||||||
retrievePlaybackActions(4));
|
|
||||||
|
|
||||||
notificationLayoutExpanded.setImageViewResource(R.id.button_toggle_play_pause,
|
|
||||||
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setUpPlaybackActions(boolean isPlaying) {
|
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.button_toggle_play_pause,
|
|
||||||
retrievePlaybackActions(1));
|
|
||||||
|
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.button_next,
|
|
||||||
retrievePlaybackActions(2));
|
|
||||||
|
|
||||||
notificationLayout.setOnClickPendingIntent(R.id.button_quit,
|
|
||||||
retrievePlaybackActions(4));
|
|
||||||
|
|
||||||
notificationLayout.setImageViewResource(R.id.button_toggle_play_pause,
|
|
||||||
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PendingIntent retrievePlaybackActions(final int which) {
|
|
||||||
Intent action;
|
|
||||||
PendingIntent pendingIntent;
|
|
||||||
final ComponentName serviceName = new ComponentName(service, MusicService.class);
|
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case 1:
|
case 0:
|
||||||
action = new Intent(MusicService.ACTION_TOGGLE_PLAYBACK);
|
actionString = MusicService.ACTION_TOGGLE_PLAYBACK;
|
||||||
action.setComponent(serviceName);
|
|
||||||
pendingIntent = PendingIntent.getService(service, 1, action, 0);
|
|
||||||
return pendingIntent;
|
|
||||||
case 2:
|
|
||||||
action = new Intent(MusicService.ACTION_SKIP);
|
|
||||||
action.setComponent(serviceName);
|
|
||||||
pendingIntent = PendingIntent.getService(service, 2, action, 0);
|
|
||||||
return pendingIntent;
|
|
||||||
case 3:
|
|
||||||
action = new Intent(MusicService.ACTION_REWIND);
|
|
||||||
action.setComponent(serviceName);
|
|
||||||
pendingIntent = PendingIntent.getService(service, 3, action, 0);
|
|
||||||
return pendingIntent;
|
|
||||||
case 4:
|
|
||||||
action = new Intent(MusicService.ACTION_QUIT);
|
|
||||||
action.setComponent(serviceName);
|
|
||||||
pendingIntent = PendingIntent.getService(service, 4, action, 0);
|
|
||||||
return pendingIntent;
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
|
actionString = MusicService.ACTION_SKIP;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
actionString = MusicService.ACTION_REWIND;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
actionString = MusicService.ACTION_QUIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (actionString != null) {
|
||||||
|
final ComponentName serviceName = new ComponentName(context, MusicService.class);
|
||||||
|
Intent actionIntent = new Intent(actionString);
|
||||||
|
actionIntent.setComponent(serviceName);
|
||||||
|
return PendingIntent.getService(context, 0, actionIntent, 0);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpCollapsedLayout() {
|
// private void loadAlbumArt() {
|
||||||
if (currentSong != null) {
|
// currentAlbumArtUri = MusicUtil.getAlbumArtUri(currentSong.albumId).toString();
|
||||||
notificationLayout.setTextViewText(R.id.song_title, currentSong.title);
|
// ImageLoader.getInstance().displayImage(currentAlbumArtUri, new NonViewAware(new ImageSize(-1, -1), ViewScaleType.CROP), new SimpleImageLoadingListener() {
|
||||||
notificationLayout.setTextViewText(R.id.song_artist, currentSong.artistName);
|
// @Override
|
||||||
}
|
// public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||||
}
|
// if (currentAlbumArtUri.equals(imageUri))
|
||||||
|
// // copy() prevents the original bitmap in the memory cache from being recycled by the remote views
|
||||||
private void setUpExpandedLayout() {
|
// setAlbumArt(loadedImage.copy(loadedImage.getConfig(), true));
|
||||||
if (currentSong != null) {
|
// }
|
||||||
notificationLayoutExpanded.setTextViewText(R.id.song_title, currentSong.title);
|
//
|
||||||
notificationLayoutExpanded.setTextViewText(R.id.song_artist, currentSong.artistName);
|
// @Override
|
||||||
notificationLayoutExpanded.setTextViewText(R.id.album_title, currentSong.albumName);
|
// public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||||
}
|
// if (currentAlbumArtUri.equals(imageUri))
|
||||||
}
|
// setAlbumArt(null);
|
||||||
|
// }
|
||||||
private void loadAlbumArt() {
|
// });
|
||||||
currentAlbumArtUri = MusicUtil.getAlbumArtUri(currentSong.albumId).toString();
|
// }
|
||||||
ImageLoader.getInstance().displayImage(currentAlbumArtUri, new NonViewAware(new ImageSize(-1, -1), ViewScaleType.CROP), new SimpleImageLoadingListener() {
|
|
||||||
@Override
|
|
||||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
|
||||||
if (currentAlbumArtUri.equals(imageUri))
|
|
||||||
// copy() prevents the original bitmap in the memory cache from being recycled by the remote views
|
|
||||||
setAlbumArt(loadedImage.copy(loadedImage.getConfig(), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
|
||||||
if (currentAlbumArtUri.equals(imageUri))
|
|
||||||
setAlbumArt(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAlbumArt(Bitmap albumArt) {
|
|
||||||
if (albumArt != null) {
|
|
||||||
notificationLayout.setImageViewBitmap(R.id.album_art, albumArt);
|
|
||||||
notificationLayoutExpanded.setImageViewBitmap(R.id.album_art, albumArt);
|
|
||||||
} else {
|
|
||||||
notificationLayout.setImageViewResource(R.id.album_art, R.drawable.default_album_art);
|
|
||||||
notificationLayoutExpanded.setImageViewResource(R.id.album_art, R.drawable.default_album_art);
|
|
||||||
}
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void killNotification() {
|
|
||||||
service.stopForeground(true);
|
|
||||||
notification = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updatePlayState(final boolean isPlaying) {
|
|
||||||
if (notification == null || notificationManager == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (notificationLayout != null) {
|
|
||||||
notificationLayout.setImageViewResource(R.id.button_toggle_play_pause,
|
|
||||||
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
|
|
||||||
}
|
|
||||||
if (notificationLayoutExpanded != null) {
|
|
||||||
notificationLayoutExpanded.setImageViewResource(R.id.button_toggle_play_pause,
|
|
||||||
isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
|
|
||||||
}
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.kabouzeid.gramophone.service;
|
package com.kabouzeid.gramophone.service;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
|
@ -10,10 +12,8 @@ import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.MediaMetadata;
|
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
import android.media.audiofx.AudioEffect;
|
import android.media.audiofx.AudioEffect;
|
||||||
import android.media.session.PlaybackState;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
@ -33,6 +33,7 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.appwidget.MusicPlayerWidget;
|
import com.kabouzeid.gramophone.appwidget.MusicPlayerWidget;
|
||||||
|
import com.kabouzeid.gramophone.helper.MediaSessionHelper;
|
||||||
import com.kabouzeid.gramophone.helper.PlayingNotificationHelper;
|
import com.kabouzeid.gramophone.helper.PlayingNotificationHelper;
|
||||||
import com.kabouzeid.gramophone.helper.ShuffleHelper;
|
import com.kabouzeid.gramophone.helper.ShuffleHelper;
|
||||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||||
|
|
@ -56,6 +57,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
public static final String PHONOGRAPH_PACKAGE_NAME = "com.kabouzeid.gramophone";
|
public static final String PHONOGRAPH_PACKAGE_NAME = "com.kabouzeid.gramophone";
|
||||||
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
|
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
|
||||||
|
|
||||||
|
public static final int NOTIFICATION_ID = 1337;
|
||||||
|
|
||||||
public static final String ACTION_TOGGLE_PLAYBACK = "com.kabouzeid.gramophone.action.TOGGLE_PLAYBACK";
|
public static final String ACTION_TOGGLE_PLAYBACK = "com.kabouzeid.gramophone.action.TOGGLE_PLAYBACK";
|
||||||
public static final String ACTION_PLAY = "com.kabouzeid.gramophone.action.PLAY";
|
public static final String ACTION_PLAY = "com.kabouzeid.gramophone.action.PLAY";
|
||||||
public static final String ACTION_RESUME = "com.kabouzeid.gramophone.action.RESUME";
|
public static final String ACTION_RESUME = "com.kabouzeid.gramophone.action.RESUME";
|
||||||
|
|
@ -69,7 +72,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
public static final String PLAYSTATE_CHANGED = "com.kabouzeid.gramophone.playstatechanged";
|
public static final String PLAYSTATE_CHANGED = "com.kabouzeid.gramophone.playstatechanged";
|
||||||
public static final String REPEATMODE_CHANGED = "com.kabouzeid.gramophone.repeatmodechanged";
|
public static final String REPEATMODE_CHANGED = "com.kabouzeid.gramophone.repeatmodechanged";
|
||||||
public static final String SHUFFLEMODE_CHANGED = "com.kabouzeid.gramophone.shufflemodechanged";
|
public static final String SHUFFLEMODE_CHANGED = "com.kabouzeid.gramophone.shufflemodechanged";
|
||||||
public static final String POSITION_CHANGED = "com.kabouzeid.phonograph.positionchanged";
|
public static final String POSITION_IN_SONG_CHANGED = "com.kabouzeid.phonograph.positionchanged";
|
||||||
|
|
||||||
private static final int FOCUSCHANGE = 5;
|
private static final int FOCUSCHANGE = 5;
|
||||||
private static final int DUCK = 6;
|
private static final int DUCK = 6;
|
||||||
|
|
@ -97,14 +100,14 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
private boolean thingsRegistered;
|
private boolean thingsRegistered;
|
||||||
private boolean saveQueuesAgain;
|
private boolean saveQueuesAgain;
|
||||||
private boolean isSavingQueues;
|
private boolean isSavingQueues;
|
||||||
private PlayingNotificationHelper playingNotificationHelper;
|
|
||||||
private AudioManager audioManager;
|
private AudioManager audioManager;
|
||||||
private MediaSessionCompat mSession;
|
private MediaSessionCompat mediaSession;
|
||||||
private PowerManager.WakeLock wakeLock;
|
private PowerManager.WakeLock wakeLock;
|
||||||
private String currentAlbumArtUri;
|
private String currentAlbumArtUri;
|
||||||
private MusicPlayerHandler playerHandler;
|
private MusicPlayerHandler playerHandler;
|
||||||
private boolean fadingDown = false;
|
private boolean fadingDown = false;
|
||||||
private HandlerThread handlerThread;
|
private HandlerThread handlerThread;
|
||||||
|
private NotificationManager notificationManager;
|
||||||
|
|
||||||
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
|
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -129,7 +132,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
isPlayerPrepared = false;
|
isPlayerPrepared = false;
|
||||||
playingQueue = new ArrayList<>();
|
playingQueue = new ArrayList<>();
|
||||||
originalPlayingQueue = new ArrayList<>();
|
originalPlayingQueue = new ArrayList<>();
|
||||||
playingNotificationHelper = new PlayingNotificationHelper(this);
|
|
||||||
|
|
||||||
shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_SHUFFLE_MODE, 0);
|
shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_SHUFFLE_MODE, 0);
|
||||||
repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_REPEAT_MODE, 0);
|
repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_REPEAT_MODE, 0);
|
||||||
|
|
@ -143,18 +145,16 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
handlerThread.start();
|
handlerThread.start();
|
||||||
playerHandler = new MusicPlayerHandler(this, handlerThread.getLooper());
|
playerHandler = new MusicPlayerHandler(this, handlerThread.getLooper());
|
||||||
|
|
||||||
registerEverything();
|
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
setUpMediaSession();
|
setUpMediaSession();
|
||||||
|
|
||||||
|
registerEverything();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpMediaSession() {
|
private void setUpMediaSession() {
|
||||||
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
mediaSession = new MediaSessionCompat(this, "Phonograph", new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class), getMediaButtonIntent());
|
||||||
mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
|
mediaSession.setCallback(new MediaSessionCompat.Callback() {
|
||||||
PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
|
|
||||||
|
|
||||||
mSession = new MediaSessionCompat(this, "Phonograph", new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class), mediaPendingIntent);
|
|
||||||
mSession.setCallback(new MediaSessionCompat.Callback() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
pausePlaying(false);
|
pausePlaying(false);
|
||||||
|
|
@ -186,7 +186,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
stopPlaying();
|
stopPlaying();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
|
||||||
|
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerEverything() {
|
private void registerEverything() {
|
||||||
|
|
@ -205,17 +206,10 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
return audioManager;
|
return audioManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRemoteControlClient() {
|
private PendingIntent getMediaButtonIntent() {
|
||||||
// Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||||
// mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
|
mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
|
||||||
// PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
|
return PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
|
||||||
// remoteControlClient = new RemoteControlClient(mediaPendingIntent);
|
|
||||||
// remoteControlClient.setTransportControlFlags(
|
|
||||||
// RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
|
|
||||||
// RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
|
|
||||||
// RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
|
|
||||||
// RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
|
|
||||||
// getAudioManager().registerRemoteControlClient(remoteControlClient);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -292,7 +286,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
|
|
||||||
private void killEverythingAndReleaseResources() {
|
private void killEverythingAndReleaseResources() {
|
||||||
stopPlaying();
|
stopPlaying();
|
||||||
playingNotificationHelper.killNotification();
|
stopForeground(true);
|
||||||
savePosition();
|
savePosition();
|
||||||
saveQueues();
|
saveQueues();
|
||||||
stopSelf();
|
stopSelf();
|
||||||
|
|
@ -306,8 +300,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
player.release();
|
player.release();
|
||||||
player = null;
|
player = null;
|
||||||
}
|
}
|
||||||
mSession.setActive(false);
|
mediaSession.setActive(false);
|
||||||
mSession.release();
|
mediaSession.release();
|
||||||
notifyChange(PLAYSTATE_CHANGED);
|
notifyChange(PLAYSTATE_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,13 +377,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||||
player.setDataSource(getApplicationContext(), trackUri);
|
player.setDataSource(getApplicationContext(), trackUri);
|
||||||
player.prepareAsync();
|
player.prepareAsync();
|
||||||
} catch (Exception e) {
|
} catch (Exception ignored) {
|
||||||
player.reset();
|
// handled in onError()
|
||||||
player = null;
|
|
||||||
notifyChange(PLAYSTATE_CHANGED);
|
|
||||||
|
|
||||||
Toast.makeText(getApplicationContext(), getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
currentSongId = playingQueue.get(getPosition()).id;
|
currentSongId = playingQueue.get(getPosition()).id;
|
||||||
notifyChange(META_CHANGED);
|
notifyChange(META_CHANGED);
|
||||||
|
|
@ -426,24 +415,26 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
final Song song = playingQueue.get(getPosition());
|
final Song song = playingQueue.get(getPosition());
|
||||||
|
|
||||||
int playState = isPlaying()
|
int playState = isPlaying()
|
||||||
? PlaybackState.STATE_PLAYING
|
? PlaybackStateCompat.STATE_PLAYING
|
||||||
: PlaybackState.STATE_PAUSED;
|
: PlaybackStateCompat.STATE_PAUSED;
|
||||||
|
|
||||||
if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_CHANGED)) {
|
if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_IN_SONG_CHANGED)) {
|
||||||
mSession.setPlaybackState(new PlaybackStateCompat.Builder()
|
MediaSessionHelper.applyState(mediaSession, new PlaybackStateCompat.Builder()
|
||||||
.setState(playState, getSongProgressMillis(), 1.0f).build());
|
.setActions(getAvailablePlaybackStateActions())
|
||||||
|
.setState(playState, player != null ? getSongProgressMillis() : 0, 1.0f).build());
|
||||||
} else if (what.equals(META_CHANGED)) {
|
} else if (what.equals(META_CHANGED)) {
|
||||||
mSession.setMetadata(new MediaMetadataCompat.Builder()
|
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
|
||||||
.putString(MediaMetadata.METADATA_KEY_ARTIST, song.artistName)
|
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, song.artistName)
|
||||||
.putString(MediaMetadata.METADATA_KEY_ALBUM, song.albumName)
|
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, song.albumName)
|
||||||
.putString(MediaMetadata.METADATA_KEY_TITLE, song.title)
|
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.title)
|
||||||
.putLong(MediaMetadata.METADATA_KEY_DURATION, song.duration)
|
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, song.duration)
|
||||||
.putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, getPosition() + 1)
|
.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, getPosition() + 1)
|
||||||
.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size())
|
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size())
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
mSession.setPlaybackState(new PlaybackStateCompat.Builder()
|
MediaSessionHelper.applyState(mediaSession, new PlaybackStateCompat.Builder()
|
||||||
.setState(playState, getSongProgressMillis(), 1.0f).build());
|
.setActions(getAvailablePlaybackStateActions())
|
||||||
|
.setState(playState, player != null ? getSongProgressMillis() : 0, 1.0f).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
currentAlbumArtUri = MusicUtil.getAlbumArtUri(song.albumId).toString();
|
currentAlbumArtUri = MusicUtil.getAlbumArtUri(song.albumId).toString();
|
||||||
|
|
@ -474,14 +465,34 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateMediaSessionBitmap(final Bitmap albumArt) {
|
private void updateMediaSessionBitmap(final Bitmap albumArt) {
|
||||||
MediaMetadataCompat current = mSession.getController().getMetadata();
|
MediaMetadataCompat current = mediaSession.getController().getMetadata();
|
||||||
if (current == null) current = new MediaMetadataCompat.Builder().build();
|
if (current == null) current = new MediaMetadataCompat.Builder().build();
|
||||||
|
|
||||||
mSession.setMetadata(new MediaMetadataCompat.Builder(current)
|
mediaSession.setMetadata(new MediaMetadataCompat.Builder(current)
|
||||||
.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, albumArt)
|
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long getAvailablePlaybackStateActions() {
|
||||||
|
if (getPlayingQueue() == null || getPlayingQueue().isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long actions = PlaybackStateCompat.ACTION_PLAY_PAUSE;
|
||||||
|
if (isPlaying()) {
|
||||||
|
actions |= PlaybackStateCompat.ACTION_PAUSE;
|
||||||
|
} else {
|
||||||
|
actions |= PlaybackStateCompat.ACTION_PLAY;
|
||||||
|
}
|
||||||
|
if (getPosition() > 0) {
|
||||||
|
actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
||||||
|
}
|
||||||
|
if (getPosition() < getPlayingQueue().size() - 1) {
|
||||||
|
actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpMediaPlayerIfNeeded() {
|
private void setUpMediaPlayerIfNeeded() {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
player = new MediaPlayer();
|
player = new MediaPlayer();
|
||||||
|
|
@ -496,7 +507,14 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateNotification() {
|
private void updateNotification() {
|
||||||
playingNotificationHelper.buildNotification(playingQueue.get(position), isPlaying());
|
final boolean isPlaying = isPlaying();
|
||||||
|
Notification notification = PlayingNotificationHelper.buildNotification(this, mediaSession.getSessionToken(), getPlayingQueue().get(getPosition()), isPlaying);
|
||||||
|
if (isPlaying)
|
||||||
|
startForeground(NOTIFICATION_ID, notification);
|
||||||
|
else {
|
||||||
|
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||||
|
stopForeground(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateWidgets() {
|
private void updateWidgets() {
|
||||||
|
|
@ -568,6 +586,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
player.reset();
|
player.reset();
|
||||||
player = null;
|
player = null;
|
||||||
notifyChange(PLAYSTATE_CHANGED);
|
notifyChange(PLAYSTATE_CHANGED);
|
||||||
|
Toast.makeText(getApplicationContext(), getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -723,7 +742,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resumePlaying(boolean forceNoFading) {
|
public void resumePlaying(boolean forceNoFading) {
|
||||||
mSession.setActive(true);
|
mediaSession.setActive(true);
|
||||||
if (!forceNoFading && PreferenceUtils.getInstance(this).fadePlayPauseAndInterruptions()) {
|
if (!forceNoFading && PreferenceUtils.getInstance(this).fadePlayPauseAndInterruptions()) {
|
||||||
playerHandler.removeMessages(FADEDOWNANDPAUSE);
|
playerHandler.removeMessages(FADEDOWNANDPAUSE);
|
||||||
playerHandler.sendEmptyMessage(FADEUPANDRESUME);
|
playerHandler.sendEmptyMessage(FADEUPANDRESUME);
|
||||||
|
|
@ -805,6 +824,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
|
|
||||||
public void seekTo(int millis) {
|
public void seekTo(int millis) {
|
||||||
player.seekTo(millis);
|
player.seekTo(millis);
|
||||||
|
notifyChange(POSITION_IN_SONG_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPlayerPrepared() {
|
public boolean isPlayerPrepared() {
|
||||||
|
|
@ -864,7 +884,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
|
|
||||||
private void notifyChange(final String what) {
|
private void notifyChange(final String what) {
|
||||||
updateMediaSession(what);
|
updateMediaSession(what);
|
||||||
if (what.equals(POSITION_CHANGED)) {
|
if (what.equals(POSITION_IN_SONG_CHANGED)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -887,7 +907,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
|
|
||||||
if (what.equals(PLAYSTATE_CHANGED)) {
|
if (what.equals(PLAYSTATE_CHANGED)) {
|
||||||
final boolean isPlaying = isPlaying();
|
final boolean isPlaying = isPlaying();
|
||||||
playingNotificationHelper.updatePlayState(isPlaying);
|
updateNotification();
|
||||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying);
|
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying);
|
||||||
} else if (what.equals(META_CHANGED)) {
|
} else if (what.equals(META_CHANGED)) {
|
||||||
updateNotification();
|
updateNotification();
|
||||||
|
|
@ -962,7 +982,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
service.fadingDown = true;
|
service.fadingDown = true;
|
||||||
service.notifyChange(PLAYSTATE_CHANGED);
|
service.notifyChange(PLAYSTATE_CHANGED);
|
||||||
}
|
}
|
||||||
currentPlayPauseFadeVolume -= .1f;
|
currentPlayPauseFadeVolume -= .2f;
|
||||||
if (currentPlayPauseFadeVolume > 0f) {
|
if (currentPlayPauseFadeVolume > 0f) {
|
||||||
sendEmptyMessageDelayed(FADEDOWNANDPAUSE, 10);
|
sendEmptyMessageDelayed(FADEDOWNANDPAUSE, 10);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -980,7 +1000,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
||||||
service.notifyChange(PLAYSTATE_CHANGED);
|
service.notifyChange(PLAYSTATE_CHANGED);
|
||||||
}
|
}
|
||||||
service.resume();
|
service.resume();
|
||||||
currentPlayPauseFadeVolume += .1f;
|
currentPlayPauseFadeVolume += .2f;
|
||||||
if (currentPlayPauseFadeVolume < 1.0f) {
|
if (currentPlayPauseFadeVolume < 1.0f) {
|
||||||
sendEmptyMessageDelayed(FADEUPANDRESUME, 10);
|
sendEmptyMessageDelayed(FADEUPANDRESUME, 10);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
BIN
app/src/main/res/drawable-hdpi/ic_pause_white_36dp.png
Normal file
|
After Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 215 B |
BIN
app/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png
Normal file
|
After Width: | Height: | Size: 294 B |
|
Before Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/ic_skip_next_white_36dp.png
Normal file
|
After Width: | Height: | Size: 304 B |
BIN
app/src/main/res/drawable-hdpi/ic_skip_previous_white_36dp.png
Normal file
|
After Width: | Height: | Size: 334 B |
BIN
app/src/main/res/drawable-mdpi/ic_pause_white_36dp.png
Normal file
|
After Width: | Height: | Size: 126 B |
|
Before Width: | Height: | Size: 193 B |
BIN
app/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png
Normal file
|
After Width: | Height: | Size: 231 B |
|
Before Width: | Height: | Size: 318 B |
BIN
app/src/main/res/drawable-mdpi/ic_skip_next_white_36dp.png
Normal file
|
After Width: | Height: | Size: 216 B |
BIN
app/src/main/res/drawable-mdpi/ic_skip_previous_white_36dp.png
Normal file
|
After Width: | Height: | Size: 235 B |
BIN
app/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
Normal file
|
After Width: | Height: | Size: 183 B |
|
Before Width: | Height: | Size: 256 B |
BIN
app/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png
Normal file
|
After Width: | Height: | Size: 367 B |
|
Before Width: | Height: | Size: 477 B |
BIN
app/src/main/res/drawable-xhdpi/ic_skip_next_white_36dp.png
Normal file
|
After Width: | Height: | Size: 368 B |
BIN
app/src/main/res/drawable-xhdpi/ic_skip_previous_white_36dp.png
Normal file
|
After Width: | Height: | Size: 373 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png
Normal file
|
After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 352 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png
Normal file
|
After Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 666 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_skip_next_white_36dp.png
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_skip_previous_white_36dp.png
Normal file
|
After Width: | Height: | Size: 552 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_pause_white_36dp.png
Normal file
|
After Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 436 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_36dp.png
Normal file
|
After Width: | Height: | Size: 651 B |
|
Before Width: | Height: | Size: 835 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_skip_next_white_36dp.png
Normal file
|
After Width: | Height: | Size: 749 B |
|
After Width: | Height: | Size: 728 B |
|
|
@ -1,88 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright (C) 2014 The Android Open Source Project
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="64dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/album_art"
|
|
||||||
android:layout_width="@dimen/notification_big_icon_width"
|
|
||||||
android:layout_height="@dimen/notification_big_icon_height"
|
|
||||||
android:layout_weight="0"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="fill_vertical"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:minHeight="@dimen/notification_big_icon_height"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/notification_info_container_padding_bottom"
|
|
||||||
android:paddingStart="@dimen/notification_info_container_padding_left">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification.Title" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/media_actions"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginLeft="6dp"
|
|
||||||
android:layout_marginRight="6dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
tools:ignore="ContentDescription">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_toggle_play_pause"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:src="@drawable/ic_play_arrow_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_next"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:src="@drawable/ic_skip_next_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_quit"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_close_white_24dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright (C) 2014 The Android Open Source Project
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Layout to be used with only max 3 actions. It has a much larger picture at the left side-->
|
|
||||||
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/status_bar_latest_event_content"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="128dp"
|
|
||||||
tools:ignore="ContentDescription">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/album_art"
|
|
||||||
android:layout_width="128dp"
|
|
||||||
android:layout_height="128dp"
|
|
||||||
android:scaleType="centerCrop" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_quit"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="@drawable/notification_selector"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_close_white_24dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_toStartOf="@+id/button_quit"
|
|
||||||
android:layout_toEndOf="@+id/album_art"
|
|
||||||
android:gravity="center"
|
|
||||||
android:minHeight="@dimen/notification_big_icon_height"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingTop="12dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification.Title" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/album_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/media_actions"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:layout_toEndOf="@+id/album_art"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_prev"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_skip_previous_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_toggle_play_pause"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_play_arrow_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_next"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_skip_next_white_48dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/action_divider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_above="@+id/media_actions"
|
|
||||||
android:layout_toEndOf="@+id/album_art"
|
|
||||||
android:background="@drawable/notification_template_divider_media" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright (C) 2014 The Android Open Source Project
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
tools:ignore="ContentDescription">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/album_art"
|
|
||||||
android:layout_width="@dimen/notification_big_icon_width"
|
|
||||||
android:layout_height="@dimen/notification_big_icon_height"
|
|
||||||
android:layout_weight="0"
|
|
||||||
android:scaleType="centerCrop" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="fill_vertical"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:minHeight="@dimen/notification_big_icon_height"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/notification_info_container_padding_bottom"
|
|
||||||
android:paddingLeft="@dimen/notification_info_container_padding_left"
|
|
||||||
android:paddingStart="@dimen/notification_info_container_padding_left">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification.Title" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/media_actions"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginLeft="6dp"
|
|
||||||
android:layout_marginRight="6dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_toggle_play_pause"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:src="@drawable/ic_play_arrow_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_next"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:src="@drawable/ic_skip_next_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_quit"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_close_white_24dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright (C) 2014 The Android Open Source Project
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Layout to be used with only max 3 actions. It has a much larger picture at the left side-->
|
|
||||||
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/status_bar_latest_event_content"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="128dp"
|
|
||||||
tools:ignore="ContentDescription">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/album_art"
|
|
||||||
android:layout_width="@dimen/notification_albumart_size"
|
|
||||||
android:layout_height="@dimen/notification_albumart_size"
|
|
||||||
android:scaleType="centerCrop" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_quit"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?android:selectableItemBackground"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_close_white_24dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_toLeftOf="@+id/button_quit"
|
|
||||||
android:layout_toStartOf="@+id/button_quit"
|
|
||||||
android:layout_toRightOf="@+id/album_art"
|
|
||||||
android:layout_toEndOf="@+id/album_art"
|
|
||||||
android:gravity="center"
|
|
||||||
android:minHeight="@dimen/notification_big_icon_height"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingTop="12dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification.Title" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/song_artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/album_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/media_actions"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:layout_toRightOf="@+id/album_art"
|
|
||||||
android:layout_toEndOf="@+id/album_art"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_prev"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_skip_previous_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_toggle_play_pause"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_play_arrow_white_48dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/button_next"
|
|
||||||
style="@style/NotificationButton"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/ic_skip_next_white_48dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/action_divider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_above="@+id/media_actions"
|
|
||||||
android:layout_toRightOf="@+id/album_art"
|
|
||||||
android:layout_toEndOf="@+id/album_art"
|
|
||||||
android:background="@drawable/notification_template_divider_media" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||