diff --git a/app/build.gradle b/app/build.gradle
index f09b20a4..6eee6967 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -26,8 +26,8 @@ android {
applicationId "com.kabouzeid.gramophone"
minSdkVersion 16
targetSdkVersion 22
- versionCode 38
- versionName "0.9.22b dev-1"
+ versionCode 39
+ versionName "0.9.23b dev-1"
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9a872428..2aef90ab 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -31,6 +31,11 @@
+
+
+
+
+
diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/MusicPlayerRemote.java b/app/src/main/java/com/kabouzeid/gramophone/helper/MusicPlayerRemote.java
index 4bb80317..6126f650 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/helper/MusicPlayerRemote.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/helper/MusicPlayerRemote.java
@@ -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 playingQueue;
private static ArrayList 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 playingQueue, final int startPosition, final boolean startPlaying) {
MusicPlayerRemote.playingQueue = playingQueue;
+ position = startPosition;
+ startAfterConnected = startPlaying;
if (musicService != null) {
musicService.openQueue(MusicPlayerRemote.playingQueue, startPosition, startPlaying);
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java
index 78699339..f401cb3d 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java
@@ -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);
+ }
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/SearchQueryHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/SearchQueryHelper.java
new file mode 100644
index 00000000..097f0cff
--- /dev/null
+++ b/app/src/main/java/com/kabouzeid/gramophone/helper/SearchQueryHelper.java
@@ -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 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 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);
+ }
+}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/loader/AlbumLoader.java b/app/src/main/java/com/kabouzeid/gramophone/loader/AlbumLoader.java
index 24cdfd55..c3d4275c 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/loader/AlbumLoader.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/loader/AlbumLoader.java
@@ -17,12 +17,26 @@ import java.util.List;
public class AlbumLoader {
public static List getAllAlbums(Context context) {
- Cursor cursor = makeAlbumCursor(context);
+ Cursor cursor = makeAlbumCursor(context, null, null);
+ return getAlbums(cursor);
+ }
+
+ public static List getAlbums(Context context, String query) {
+ Cursor cursor = makeAlbumCursor(context, MediaStore.Audio.AlbumColumns.ALBUM + " LIKE ?", new String[]{"%" + query + "%"});
+ return getAlbums(cursor);
+ }
+
+ public static Album getAlbum(Context context, int albumId) {
+ Cursor cursor = makeAlbumCursor(context, BaseColumns._ID + "=?", new String[]{String.valueOf(albumId)});
+ return getAlbum(cursor);
+ }
+
+ public static List getAlbums(Cursor cursor) {
List albums = new ArrayList<>();
if (cursor != null && cursor.moveToFirst()) {
do {
- final int id = cursor.getInt(0);
final String albumName = cursor.getString(1);
+ final int id = cursor.getInt(0);
final String artist = cursor.getString(2);
final int artistId = cursor.getInt(3);
final int songCount = cursor.getInt(4);
@@ -38,8 +52,23 @@ public class AlbumLoader {
return albums;
}
- public static Cursor makeAlbumCursor(final Context context) {
- return makeAlbumCursor(context, null, null);
+ public static Album getAlbum(Cursor cursor) {
+ Album album = new Album();
+ if (cursor != null && cursor.moveToFirst()) {
+ final int id = cursor.getInt(0);
+ final String albumName = cursor.getString(1);
+ final String artist = cursor.getString(2);
+ final int artistId = cursor.getInt(3);
+ final int songCount = cursor.getInt(4);
+ final int year = cursor.getInt(5);
+
+ album = new Album(id, albumName, artist, artistId, songCount, year);
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+ return album;
}
public static Cursor makeAlbumCursor(final Context context, final String selection, final String[] values) {
@@ -59,46 +88,4 @@ public class AlbumLoader {
MediaStore.Audio.AlbumColumns.FIRST_YEAR,
}, selection, values, PreferenceUtils.getInstance(context).getAlbumSortOrder());
}
-
- public static Album getAlbum(Context context, int albumId) {
- Cursor cursor = makeAlbumCursor(context, BaseColumns._ID + "=?", new String[]{String.valueOf(albumId)});
- Album album = new Album();
- if (cursor != null && cursor.moveToFirst()) {
- final int id = cursor.getInt(0);
- final String albumName = cursor.getString(1);
- final String artist = cursor.getString(2);
- final int artistId = cursor.getInt(3);
- final int songCount = cursor.getInt(4);
- final int year = cursor.getInt(5);
-
- album = new Album(id, albumName, artist, artistId, songCount, year);
- }
-
- if (cursor != null) {
- cursor.close();
- }
- return album;
- }
-
- public static List getAlbums(Context context, String query) {
- Cursor cursor = makeAlbumCursor(context, MediaStore.Audio.AlbumColumns.ALBUM + " LIKE ?", new String[]{"%" + query + "%"});
- List albums = new ArrayList<>();
- if (cursor != null && cursor.moveToFirst()) {
- do {
- final String albumName = cursor.getString(1);
- final int id = cursor.getInt(0);
- final String artist = cursor.getString(2);
- final int artistId = cursor.getInt(3);
- final int songCount = cursor.getInt(4);
- final int year = cursor.getInt(5);
-
- final Album album = new Album(id, albumName, artist, artistId, songCount, year);
- albums.add(album);
- } while (cursor.moveToNext());
- }
- if (cursor != null) {
- cursor.close();
- }
- return albums;
- }
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/loader/ArtistLoader.java b/app/src/main/java/com/kabouzeid/gramophone/loader/ArtistLoader.java
index 645de99c..6dbc2d0c 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/loader/ArtistLoader.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/loader/ArtistLoader.java
@@ -17,12 +17,26 @@ import java.util.List;
public class ArtistLoader {
public static List getAllArtists(Context context) {
- Cursor cursor = makeArtistCursor(context);
+ Cursor cursor = makeArtistCursor(context, null, null);
+ return getArtists(cursor);
+ }
+
+ public static List getArtists(Context context, String query) {
+ Cursor cursor = makeArtistCursor(context, MediaStore.Audio.ArtistColumns.ARTIST + " LIKE ?", new String[]{"%" + query + "%"});
+ return getArtists(cursor);
+ }
+
+ public static Artist getArtist(Context context, int artistId) {
+ Cursor cursor = makeArtistCursor(context, BaseColumns._ID + "=?", new String[]{String.valueOf(artistId)});
+ return getArtist(cursor);
+ }
+
+ public static List getArtists(Cursor cursor) {
List artists = new ArrayList<>();
if (cursor != null && cursor.moveToFirst()) {
do {
- final int id = cursor.getInt(0);
final String artistName = cursor.getString(1);
+ final int id = cursor.getInt(0);
final int albumCount = cursor.getInt(2);
final int songCount = cursor.getInt(3);
@@ -30,31 +44,14 @@ public class ArtistLoader {
artists.add(artist);
} while (cursor.moveToNext());
}
- if (cursor != null)
+
+ if (cursor != null) {
cursor.close();
+ }
return artists;
}
- public static Cursor makeArtistCursor(final Context context) {
- return makeArtistCursor(context, null, null);
- }
-
- public static Cursor makeArtistCursor(final Context context, final String selection, final String[] values) {
- return context.getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
- new String[]{
- /* 0 */
- BaseColumns._ID,
- /* 1 */
- MediaStore.Audio.ArtistColumns.ARTIST,
- /* 2 */
- MediaStore.Audio.ArtistColumns.NUMBER_OF_ALBUMS,
- /* 3 */
- MediaStore.Audio.ArtistColumns.NUMBER_OF_TRACKS
- }, selection, values, PreferenceUtils.getInstance(context).getArtistSortOrder());
- }
-
- public static Artist getArtist(Context context, int artistId) {
- Cursor cursor = makeArtistCursor(context, BaseColumns._ID + "=?", new String[]{String.valueOf(artistId)});
+ public static Artist getArtist(Cursor cursor) {
Artist artist = new Artist();
if (cursor != null && cursor.moveToFirst()) {
final int id = cursor.getInt(0);
@@ -71,24 +68,17 @@ public class ArtistLoader {
return artist;
}
- public static List getArtists(Context context, String query) {
- Cursor cursor = makeArtistCursor(context, MediaStore.Audio.ArtistColumns.ARTIST + " LIKE ?", new String[]{"%" + query + "%"});
- List artists = new ArrayList<>();
- if (cursor != null && cursor.moveToFirst()) {
- do {
- final String artistName = cursor.getString(1);
- final int id = cursor.getInt(0);
- final int albumCount = cursor.getInt(2);
- final int songCount = cursor.getInt(3);
-
- final Artist artist = new Artist(id, artistName, albumCount, songCount);
- artists.add(artist);
- } while (cursor.moveToNext());
- }
-
- if (cursor != null) {
- cursor.close();
- }
- return artists;
+ public static Cursor makeArtistCursor(final Context context, final String selection, final String[] values) {
+ return context.getContentResolver().query(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
+ new String[]{
+ /* 0 */
+ BaseColumns._ID,
+ /* 1 */
+ MediaStore.Audio.ArtistColumns.ARTIST,
+ /* 2 */
+ MediaStore.Audio.ArtistColumns.NUMBER_OF_ALBUMS,
+ /* 3 */
+ MediaStore.Audio.ArtistColumns.NUMBER_OF_TRACKS
+ }, selection, values, PreferenceUtils.getInstance(context).getArtistSortOrder());
}
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java b/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java
index 0bc8607c..e3e333a5 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java
@@ -9,7 +9,6 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.PreferenceUtils;
import java.util.ArrayList;
-import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
@@ -18,12 +17,26 @@ public class SongLoader {
private static final String BASE_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1" + " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''";
public static ArrayList getAllSongs(Context context) {
- Cursor cursor = makeSongCursor(context);
+ Cursor cursor = makeSongCursor(context, null, null);
+ return getSongs(cursor);
+ }
+
+ public static ArrayList getSongs(final Context context, final String query) {
+ Cursor cursor = makeSongCursor(context, MediaStore.Audio.AudioColumns.TITLE + " LIKE ?", new String[]{"%" + query + "%"});
+ return getSongs(cursor);
+ }
+
+ public static Song getSong(final Context context, final int queryId) {
+ Cursor cursor = makeSongCursor(context, MediaStore.Audio.AudioColumns._ID + "=?", new String[]{String.valueOf(queryId)});
+ return getSong(cursor);
+ }
+
+ public static ArrayList getSongs(final Cursor cursor) {
ArrayList songs = new ArrayList<>();
if (cursor != null && cursor.moveToFirst()) {
do {
- final int id = cursor.getInt(0);
final String songName = cursor.getString(1);
+ final int id = cursor.getInt(0);
final String artist = cursor.getString(2);
final String album = cursor.getString(3);
final long duration = cursor.getLong(4);
@@ -35,19 +48,35 @@ public class SongLoader {
songs.add(song);
} while (cursor.moveToNext());
}
+
if (cursor != null)
cursor.close();
return songs;
}
- public static Cursor makeSongCursor(final Context context) {
- return makeSongCursor(context, MediaStore.Audio.AudioColumns.IS_MUSIC + "=?", new String[]{"1"});
+ public static Song getSong(Cursor cursor) {
+ Song song = new Song();
+ if (cursor != null && cursor.moveToFirst()) {
+ final int id = cursor.getInt(0);
+ final String songName = cursor.getString(1);
+ final String artist = cursor.getString(2);
+ final String album = cursor.getString(3);
+ final long duration = cursor.getLong(4);
+ final int trackNumber = cursor.getInt(5);
+ final int artistId = cursor.getInt(6);
+ final int albumId = cursor.getInt(7);
+ song = new Song(id, albumId, artistId, songName, artist, album, duration, trackNumber);
+ }
+ if (cursor != null) {
+ cursor.close();
+ }
+ return song;
}
public static Cursor makeSongCursor(final Context context, final String selection, final String[] values) {
- String finalSelection = BASE_SELECTION;
- if (selection != null) {
- finalSelection += " AND " + selection;
+ String baseSelection = BASE_SELECTION;
+ if (selection != null && !selection.trim().equals("")) {
+ baseSelection += " AND " + selection;
}
return context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
@@ -68,50 +97,6 @@ public class SongLoader {
MediaStore.Audio.AudioColumns.ARTIST_ID,
/* 7 */
MediaStore.Audio.AudioColumns.ALBUM_ID
- }, finalSelection, values, PreferenceUtils.getInstance(context).getSongSortOrder());
- }
-
- public static List getSongs(final Context context, final String query) {
- Cursor cursor = makeSongCursor(context, MediaStore.Audio.AudioColumns.TITLE + " LIKE ?", new String[]{"%" + query + "%"});
- List songs = new ArrayList<>();
- if (cursor != null && cursor.moveToFirst()) {
- do {
- final String songName = cursor.getString(1);
- final int id = cursor.getInt(0);
- final String artist = cursor.getString(2);
- final String album = cursor.getString(3);
- final long duration = cursor.getLong(4);
- final int trackNumber = cursor.getInt(5);
- final int artistId = cursor.getInt(6);
- final int albumId = cursor.getInt(7);
-
- final Song song = new Song(id, albumId, artistId, songName, artist, album, duration, trackNumber);
- songs.add(song);
- } while (cursor.moveToNext());
- }
-
- if (cursor != null)
- cursor.close();
- return songs;
- }
-
- public static Song getSong(final Context context, final int queryId) {
- Cursor cursor = makeSongCursor(context, MediaStore.Audio.AudioColumns._ID + "=?", new String[]{String.valueOf(queryId)});
- Song song = null;
- if (cursor != null && cursor.moveToFirst()) {
- final int id = cursor.getInt(0);
- final String songName = cursor.getString(1);
- final String artist = cursor.getString(2);
- final String album = cursor.getString(3);
- final long duration = cursor.getLong(4);
- final int trackNumber = cursor.getInt(5);
- final int artistId = cursor.getInt(6);
- final int albumId = cursor.getInt(7);
- song = new Song(id, albumId, artistId, songName, artist, album, duration, trackNumber);
- }
- if (cursor != null) {
- cursor.close();
- }
- return song;
+ }, baseSelection, values, PreferenceUtils.getInstance(context).getSongSortOrder());
}
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
index 5a964b58..d8a84498 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
@@ -1,7 +1,5 @@
package com.kabouzeid.gramophone.service;
-import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
@@ -12,10 +10,13 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.AudioManager;
+import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
+import android.media.RemoteControlClient;
import android.media.audiofx.AudioEffect;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -24,16 +25,12 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.preference.PreferenceManager;
-import android.support.v4.media.MediaMetadataCompat;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.appwidget.MusicPlayerWidget;
-import com.kabouzeid.gramophone.helper.MediaSessionHelper;
import com.kabouzeid.gramophone.helper.PlayingNotificationHelper;
import com.kabouzeid.gramophone.helper.ShuffleHelper;
import com.kabouzeid.gramophone.misc.AppKeys;
@@ -85,6 +82,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
public static final int REPEAT_MODE_NONE = 0;
public static final int REPEAT_MODE_ALL = 1;
public static final int REPEAT_MODE_THIS = 2;
+
private static final String TAG = MusicService.class.getSimpleName();
private final IBinder musicBind = new MusicBinder();
@@ -100,14 +98,14 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
private boolean thingsRegistered;
private boolean saveQueuesAgain;
private boolean isSavingQueues;
+ private PlayingNotificationHelper playingNotificationHelper;
private AudioManager audioManager;
- private MediaSessionCompat mediaSession;
+ private RemoteControlClient remoteControlClient;
private PowerManager.WakeLock wakeLock;
private String currentAlbumArtUri;
private MusicPlayerHandler playerHandler;
private boolean fadingDown = false;
private HandlerThread handlerThread;
- private NotificationManager notificationManager;
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
@@ -132,6 +130,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
isPlayerPrepared = false;
playingQueue = new ArrayList<>();
originalPlayingQueue = new ArrayList<>();
+ playingNotificationHelper = new PlayingNotificationHelper(this);
shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_SHUFFLE_MODE, 0);
repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_REPEAT_MODE, 0);
@@ -145,56 +144,16 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
handlerThread.start();
playerHandler = new MusicPlayerHandler(this, handlerThread.getLooper());
- notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-
- setUpMediaSession();
-
registerEverything();
}
- private void setUpMediaSession() {
- mediaSession = new MediaSessionCompat(this, "Phonograph", new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class), getMediaButtonIntent());
- mediaSession.setCallback(new MediaSessionCompat.Callback() {
- @Override
- public void onPause() {
- pausePlaying(false);
- }
-
- @Override
- public void onPlay() {
- resumePlaying(false);
- }
-
- @Override
- public void onSeekTo(long pos) {
- //TODO
- //seek(pos);
- }
-
- @Override
- public void onSkipToNext() {
- playNextSong(true);
- }
-
- @Override
- public void onSkipToPrevious() {
- playPreviousSong(true);
- }
-
- @Override
- public void onStop() {
- stopPlaying();
- }
- });
- mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
- MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
- }
-
private void registerEverything() {
if (!thingsRegistered) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(becomingNoisyReceiver, intentFilter);
+ getAudioManager().registerMediaButtonEventReceiver(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
+ initRemoteControlClient();
thingsRegistered = true;
}
}
@@ -206,6 +165,16 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
return audioManager;
}
+ private void initRemoteControlClient() {
+ remoteControlClient = new RemoteControlClient(getMediaButtonIntent());
+ 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);
+ }
+
private PendingIntent getMediaButtonIntent() {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
@@ -259,7 +228,11 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
unregisterEverything();
playerHandler.removeCallbacksAndMessages(null);
- handlerThread.quitSafely();
+ if (Build.VERSION.SDK_INT >= 18) {
+ handlerThread.quitSafely();
+ } else {
+ handlerThread.quit();
+ }
killEverythingAndReleaseResources();
}
@@ -279,6 +252,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
private void unregisterEverything() {
if (thingsRegistered) {
unregisterReceiver(becomingNoisyReceiver);
+ getAudioManager().unregisterRemoteControlClient(remoteControlClient);
+ getAudioManager().unregisterMediaButtonEventReceiver(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
getAudioManager().abandonAudioFocus(audioFocusListener);
thingsRegistered = false;
}
@@ -286,7 +261,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
private void killEverythingAndReleaseResources() {
stopPlaying();
- stopForeground(true);
+ playingNotificationHelper.killNotification();
savePosition();
saveQueues();
stopSelf();
@@ -300,8 +275,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
player.release();
player = null;
}
- mediaSession.setActive(false);
- mediaSession.release();
notifyChange(PLAYSTATE_CHANGED);
}
@@ -309,11 +282,11 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
return isPlaying(false);
}
- private boolean isPlaying(boolean alsoIfIsFadingDown) {
- if (!alsoIfIsFadingDown)
- return player != null && isPlayerPrepared && player.isPlaying() && !fadingDown;
- else
+ private boolean isPlaying(boolean doNotConsiderFadingDown) {
+ if (doNotConsiderFadingDown)
return player != null && isPlayerPrepared && player.isPlaying();
+ else
+ return player != null && isPlayerPrepared && player.isPlaying() && !fadingDown;
}
public void saveQueues() {
@@ -411,32 +384,14 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
return (getAudioManager().requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
}
- private void updateMediaSession(final String what) {
+ private void updateRemoteControlClient() {
final Song song = playingQueue.get(getPosition());
-
- int playState = isPlaying()
- ? PlaybackStateCompat.STATE_PLAYING
- : PlaybackStateCompat.STATE_PAUSED;
-
- if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_IN_SONG_CHANGED)) {
- MediaSessionHelper.applyState(mediaSession, new PlaybackStateCompat.Builder()
- .setActions(getAvailablePlaybackStateActions())
- .setState(playState, player != null ? getSongProgressMillis() : 0, 1.0f).build());
- } else if (what.equals(META_CHANGED)) {
- mediaSession.setMetadata(new MediaMetadataCompat.Builder()
- .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, song.artistName)
- .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, song.albumName)
- .putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.title)
- .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, song.duration)
- .putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, getPosition() + 1)
- .putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size())
- .build());
-
- MediaSessionHelper.applyState(mediaSession, new PlaybackStateCompat.Builder()
- .setActions(getAvailablePlaybackStateActions())
- .setState(playState, player != null ? getSongProgressMillis() : 0, 1.0f).build());
- }
-
+ remoteControlClient
+ .editMetadata(false)
+ .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, song.artistName)
+ .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, song.title)
+ .putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, song.duration)
+ .apply();
currentAlbumArtUri = MusicUtil.getAlbumArtUri(song.albumId).toString();
ImageLoader.getInstance().displayImage(currentAlbumArtUri, new NonViewAware(new ImageSize(-1, -1), ViewScaleType.CROP), new SimpleImageLoadingListener() {
@Override
@@ -451,7 +406,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
config = Bitmap.Config.ARGB_8888;
}
albumArt = albumArt.copy(config, false);
- updateMediaSessionBitmap(albumArt.copy(albumArt.getConfig(), true));
+ updateRemoteControlClientBitmap(albumArt.copy(albumArt.getConfig(), true));
}
}
}
@@ -459,38 +414,16 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
if (currentAlbumArtUri.equals(imageUri))
- updateMediaSessionBitmap(null);
+ updateRemoteControlClientBitmap(null);
}
});
}
- private void updateMediaSessionBitmap(final Bitmap albumArt) {
- MediaMetadataCompat current = mediaSession.getController().getMetadata();
- if (current == null) current = new MediaMetadataCompat.Builder().build();
-
- mediaSession.setMetadata(new MediaMetadataCompat.Builder(current)
- .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
- .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 updateRemoteControlClientBitmap(final Bitmap albumArt) {
+ remoteControlClient
+ .editMetadata(false)
+ .putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, albumArt)
+ .apply();
}
private void setUpMediaPlayerIfNeeded() {
@@ -507,14 +440,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
}
private void updateNotification() {
- 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);
- }
+ playingNotificationHelper.buildNotification(playingQueue.get(position), isPlaying());
}
private void updateWidgets() {
@@ -742,7 +668,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
}
public void resumePlaying(boolean forceNoFading) {
- mediaSession.setActive(true);
if (!forceNoFading && PreferenceUtils.getInstance(this).fadePlayPauseAndInterruptions()) {
playerHandler.removeMessages(FADEDOWNANDPAUSE);
playerHandler.sendEmptyMessage(FADEUPANDRESUME);
@@ -824,7 +749,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
public void seekTo(int millis) {
player.seekTo(millis);
- notifyChange(POSITION_IN_SONG_CHANGED);
}
public boolean isPlayerPrepared() {
@@ -883,11 +807,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
}
private void notifyChange(final String what) {
- updateMediaSession(what);
- if (what.equals(POSITION_IN_SONG_CHANGED)) {
- return;
- }
-
final Intent internalIntent = new Intent(what);
final int position = getPosition();
if (position >= 0 && !playingQueue.isEmpty()) {
@@ -907,11 +826,13 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
if (what.equals(PLAYSTATE_CHANGED)) {
final boolean isPlaying = isPlaying();
- updateNotification();
+ playingNotificationHelper.updatePlayState(isPlaying);
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying);
+ remoteControlClient.setPlaybackState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : RemoteControlClient.PLAYSTATE_PAUSED);
} else if (what.equals(META_CHANGED)) {
updateNotification();
updateWidgets();
+ updateRemoteControlClient();
}
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java
index 790fc939..94a25ebd 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java
@@ -38,6 +38,7 @@ import com.kabouzeid.gramophone.adapter.PagerAdapter;
import com.kabouzeid.gramophone.dialogs.AboutDialog;
import com.kabouzeid.gramophone.dialogs.CreatePlaylistDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
+import com.kabouzeid.gramophone.helper.SearchQueryHelper;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
import com.kabouzeid.gramophone.loader.AlbumSongLoader;
@@ -405,6 +406,10 @@ public class MainActivity extends AbsFabActivity
String mimeType = intent.getType();
boolean handled = false;
+ if (intent.getAction() != null
+ && intent.getAction().equals(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH)) {
+ MusicPlayerRemote.openQueue(SearchQueryHelper.getSongs(this, intent.getExtras()), 0, true);
+ }
if (uri != null && uri.toString().length() > 0) {
MusicPlayerRemote.playFile(uri);
handled = true;
diff --git a/app/src/main/res/layout/notification_controller.xml b/app/src/main/res/layout/notification_controller.xml
new file mode 100644
index 00000000..29a5a3af
--- /dev/null
+++ b/app/src/main/res/layout/notification_controller.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/notification_controller_big.xml b/app/src/main/res/layout/notification_controller_big.xml
new file mode 100644
index 00000000..3ae0a71d
--- /dev/null
+++ b/app/src/main/res/layout/notification_controller_big.xml
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 726ce8dd..9f00a5a4 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -24,6 +24,8 @@
#FFFFFF
#99FFFFFF
+ @color/grey_800
+
#29ffffff