Reverted "MediaSession update" back to RemoteControlClient. Added back the "x" to close the notification. Notification now also colored below Lollipop. Its now possible to play music from Google Now voice search.
This commit is contained in:
parent
554bc25f83
commit
1072a3bf85
13 changed files with 712 additions and 329 deletions
|
|
@ -30,6 +30,7 @@ public class MusicPlayerRemote {
|
|||
private static final String TAG = MusicPlayerRemote.class.getSimpleName();
|
||||
|
||||
private static int position = -1;
|
||||
private static boolean startAfterConnected = false;
|
||||
|
||||
private static ArrayList<Song> playingQueue;
|
||||
private static ArrayList<Song> restoredOriginalQueue;
|
||||
|
|
@ -44,6 +45,7 @@ public class MusicPlayerRemote {
|
|||
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
|
||||
musicService = binder.getService();
|
||||
musicService.restorePreviousState(restoredOriginalQueue, playingQueue, position);
|
||||
if(startAfterConnected) resumePlaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -121,6 +123,8 @@ public class MusicPlayerRemote {
|
|||
|
||||
public static void openQueue(final ArrayList<Song> playingQueue, final int startPosition, final boolean startPlaying) {
|
||||
MusicPlayerRemote.playingQueue = playingQueue;
|
||||
position = startPosition;
|
||||
startAfterConnected = startPlaying;
|
||||
if (musicService != null) {
|
||||
musicService.openQueue(MusicPlayerRemote.playingQueue, startPosition, startPlaying);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ package com.kabouzeid.gramophone.helper;
|
|||
*/
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.TaskStackBuilder;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v7.graphics.Palette;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
|
|
@ -24,87 +24,199 @@ import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
|||
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||
import com.kabouzeid.gramophone.util.PreferenceUtils;
|
||||
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 static final String TAG = PlayingNotificationHelper.class.getSimpleName();
|
||||
public static final int NOTIFICATION_ID = 1337;
|
||||
|
||||
public static Notification buildNotification(final Context context, MediaSessionCompat.Token sessionToken, final Song song, final boolean isPlaying) {
|
||||
private final MusicService service;
|
||||
|
||||
NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle()
|
||||
.setMediaSession(sessionToken)
|
||||
.setShowActionsInCompactView(0, 1, 2);
|
||||
private final NotificationManager notificationManager;
|
||||
private Notification notification = null;
|
||||
|
||||
style.setShowCancelButton(true);
|
||||
style.setCancelButtonIntent(retrievePlaybackAction(context, 3));
|
||||
private RemoteViews notificationLayout;
|
||||
private RemoteViews notificationLayoutExpanded;
|
||||
|
||||
Bitmap albumArt = ImageLoader.getInstance().loadImageSync(MusicUtil.getAlbumArtUri(song.albumId).toString());
|
||||
if (albumArt == null) {
|
||||
albumArt = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_album_art);
|
||||
}
|
||||
int notificationColor = PreferenceUtils.getInstance(context).coloredNotification() ?
|
||||
Palette.from(albumArt).generate().getVibrantColor(Color.TRANSPARENT) :
|
||||
Color.TRANSPARENT;
|
||||
private Song currentSong;
|
||||
private String currentAlbumArtUri;
|
||||
|
||||
return new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setLargeIcon(albumArt)
|
||||
.setContentIntent(getOpenMusicControllerPendingIntent(context))
|
||||
.setContentTitle(song.title)
|
||||
.setContentText(song.artistName)
|
||||
.setSubText(song.albumName)
|
||||
.setWhen(0)
|
||||
.setShowWhen(false)
|
||||
.setStyle(style)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
|
||||
.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)
|
||||
.setColor(notificationColor)
|
||||
.build();
|
||||
public PlayingNotificationHelper(final MusicService service) {
|
||||
this.service = service;
|
||||
notificationManager = (NotificationManager) service
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
private static PendingIntent getOpenMusicControllerPendingIntent(final Context context) {
|
||||
Intent result = new Intent(context, MusicControllerActivity.class);
|
||||
TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
|
||||
public void buildNotification(final Song song, final boolean isPlaying) {
|
||||
currentSong = song;
|
||||
notificationLayout = new RemoteViews(service.getPackageName(),
|
||||
R.layout.notification_controller);
|
||||
notificationLayoutExpanded = new RemoteViews(service.getPackageName(),
|
||||
R.layout.notification_controller_big);
|
||||
|
||||
notification = new NotificationCompat.Builder(service)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentIntent(getOpenMusicControllerPendingIntent())
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setContent(notificationLayout)
|
||||
.build();
|
||||
|
||||
notification.bigContentView = notificationLayoutExpanded;
|
||||
|
||||
setUpCollapsedLayout();
|
||||
setUpExpandedLayout();
|
||||
loadAlbumArt();
|
||||
setUpPlaybackActions(isPlaying);
|
||||
setUpExpandedPlaybackActions(isPlaying);
|
||||
|
||||
service.startForeground(NOTIFICATION_ID, notification);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static PendingIntent retrievePlaybackAction(final Context context, final int which) {
|
||||
String actionString = null;
|
||||
private void setUpExpandedPlaybackActions(boolean isPlaying) {
|
||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.action_play_pause,
|
||||
retrievePlaybackActions(1));
|
||||
|
||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.action_next,
|
||||
retrievePlaybackActions(2));
|
||||
|
||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.action_prev,
|
||||
retrievePlaybackActions(3));
|
||||
|
||||
notificationLayoutExpanded.setOnClickPendingIntent(R.id.action_quit,
|
||||
retrievePlaybackActions(4));
|
||||
|
||||
notificationLayoutExpanded.setImageViewResource(R.id.action_play_pause,
|
||||
isPlaying ? R.drawable.ic_pause_white_36dp : R.drawable.ic_play_arrow_white_36dp);
|
||||
}
|
||||
|
||||
private void setUpPlaybackActions(boolean isPlaying) {
|
||||
notificationLayout.setOnClickPendingIntent(R.id.action_play_pause,
|
||||
retrievePlaybackActions(1));
|
||||
|
||||
notificationLayout.setOnClickPendingIntent(R.id.action_next,
|
||||
retrievePlaybackActions(2));
|
||||
|
||||
notificationLayout.setOnClickPendingIntent(R.id.action_prev,
|
||||
retrievePlaybackActions(3));
|
||||
|
||||
notificationLayout.setImageViewResource(R.id.action_play_pause,
|
||||
isPlaying ? R.drawable.ic_pause_white_36dp : R.drawable.ic_play_arrow_white_36dp);
|
||||
}
|
||||
|
||||
private PendingIntent retrievePlaybackActions(final int which) {
|
||||
Intent action;
|
||||
PendingIntent pendingIntent;
|
||||
final ComponentName serviceName = new ComponentName(service, MusicService.class);
|
||||
switch (which) {
|
||||
case 0:
|
||||
actionString = MusicService.ACTION_TOGGLE_PLAYBACK;
|
||||
break;
|
||||
case 1:
|
||||
actionString = MusicService.ACTION_SKIP;
|
||||
break;
|
||||
action = new Intent(MusicService.ACTION_TOGGLE_PLAYBACK);
|
||||
action.setComponent(serviceName);
|
||||
pendingIntent = PendingIntent.getService(service, 1, action, 0);
|
||||
return pendingIntent;
|
||||
case 2:
|
||||
actionString = MusicService.ACTION_REWIND;
|
||||
break;
|
||||
action = new Intent(MusicService.ACTION_SKIP);
|
||||
action.setComponent(serviceName);
|
||||
pendingIntent = PendingIntent.getService(service, 2, action, 0);
|
||||
return pendingIntent;
|
||||
case 3:
|
||||
actionString = MusicService.ACTION_QUIT;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
private void setUpCollapsedLayout() {
|
||||
if (currentSong != null) {
|
||||
notificationLayout.setTextViewText(R.id.title, currentSong.title);
|
||||
notificationLayout.setTextViewText(R.id.text, currentSong.artistName);
|
||||
notificationLayout.setTextViewText(R.id.text2, currentSong.albumName);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpExpandedLayout() {
|
||||
if (currentSong != null) {
|
||||
notificationLayoutExpanded.setTextViewText(R.id.title, currentSong.title);
|
||||
notificationLayoutExpanded.setTextViewText(R.id.text, currentSong.artistName);
|
||||
notificationLayoutExpanded.setTextViewText(R.id.text2, currentSong.albumName);
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
setAlbumArt(loadedImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
if (currentAlbumArtUri.equals(imageUri))
|
||||
setAlbumArt(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setAlbumArt(Bitmap albumArt) {
|
||||
int defaultColor = service.getResources().getColor(R.color.default_notification_color);
|
||||
int newColor = defaultColor;
|
||||
if (albumArt != null) {
|
||||
notificationLayout.setImageViewBitmap(R.id.icon, albumArt);
|
||||
notificationLayoutExpanded.setImageViewBitmap(R.id.icon, albumArt);
|
||||
if (PreferenceUtils.getInstance(service).coloredNotification())
|
||||
newColor = Palette.from(albumArt).generate().getVibrantColor(defaultColor);
|
||||
} else {
|
||||
notificationLayout.setImageViewResource(R.id.icon, R.drawable.default_album_art);
|
||||
notificationLayoutExpanded.setImageViewResource(R.id.icon, R.drawable.default_album_art);
|
||||
}
|
||||
|
||||
notificationLayout.setInt(R.id.root, "setBackgroundColor", newColor);
|
||||
notificationLayoutExpanded.setInt(R.id.root, "setBackgroundColor", newColor);
|
||||
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.action_play_pause,
|
||||
isPlaying ? R.drawable.ic_pause_white_36dp : R.drawable.ic_play_arrow_white_36dp);
|
||||
}
|
||||
if (notificationLayoutExpanded != null) {
|
||||
notificationLayoutExpanded.setImageViewResource(R.id.action_play_pause,
|
||||
isPlaying ? R.drawable.ic_pause_white_36dp : R.drawable.ic_play_arrow_white_36dp);
|
||||
}
|
||||
notificationManager.notify(NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
package com.kabouzeid.gramophone.helper;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
import com.kabouzeid.gramophone.loader.SongLoader;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public class SearchQueryHelper {
|
||||
private static final String TITLE_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.TITLE + ") = ?";
|
||||
private static final String ALBUM_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.ALBUM + ") = ?";
|
||||
private static final String ARTIST_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.ARTIST + ") = ?";
|
||||
private static final String AND = " AND ";
|
||||
|
||||
public static ArrayList<Song> getSongs(final Context context, final Bundle extras) {
|
||||
final String query = extras.getString(SearchManager.QUERY, null);
|
||||
final String artistName = extras.getString(MediaStore.EXTRA_MEDIA_ARTIST, null);
|
||||
final String albumName = extras.getString(MediaStore.EXTRA_MEDIA_ALBUM, null);
|
||||
final String titleName = extras.getString(MediaStore.EXTRA_MEDIA_TITLE, null);
|
||||
|
||||
ArrayList<Song> songs = new ArrayList<>();
|
||||
|
||||
if (artistName != null && albumName != null && titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION + AND + ALBUM_SELECTION + AND + TITLE_SELECTION, new String[]{artistName.toLowerCase(), albumName.toLowerCase(), titleName.toLowerCase()}));
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
if (artistName != null && titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION + AND + TITLE_SELECTION, new String[]{artistName.toLowerCase(), titleName.toLowerCase()}));
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
if (albumName != null && titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION + AND + TITLE_SELECTION, new String[]{albumName.toLowerCase(), titleName.toLowerCase()}));
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
if (artistName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION, new String[]{artistName.toLowerCase()}));
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
if (albumName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION, new String[]{albumName.toLowerCase()}));
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
if (titleName != null) {
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, TITLE_SELECTION, new String[]{titleName.toLowerCase()}));
|
||||
}
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ARTIST_SELECTION, new String[]{query.toLowerCase()}));
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, ALBUM_SELECTION, new String[]{query.toLowerCase()}));
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, TITLE_SELECTION, new String[]{query.toLowerCase()}));
|
||||
if (!songs.isEmpty()) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
return SongLoader.getSongs(context, query);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue