From 6768540171cd815002160bf76dcee1ae57b0fb28 Mon Sep 17 00:00:00 2001 From: Renato Mangini Date: Thu, 2 Oct 2014 10:46:11 -0700 Subject: Updated MusicDemo sample. Use material icons and colors; Removed dependence on support libraries; Added album art cache; Bug: 17755718 Change-Id: I3085aa3e154393c3b0287783600f7187f7e42c7a --- MusicDemo/build.gradle | 6 +- .../musicservicedemo/MediaNotification.java | 133 +++++++++++++-------- .../musicservicedemo/utils/BitmapHelper.java | 19 --- .../main/res/drawable-hdpi/ic_pause_white_24dp.png | Bin 0 -> 188 bytes .../res/drawable-hdpi/ic_play_arrow_white_24dp.png | Bin 0 -> 282 bytes .../res/drawable-hdpi/ic_shuffle_white_24dp.png | Bin 0 -> 458 bytes .../res/drawable-hdpi/ic_skip_next_white_24dp.png | Bin 0 -> 291 bytes .../drawable-hdpi/ic_skip_previous_white_24dp.png | Bin 0 -> 306 bytes .../res/drawable-xhdpi/ic_pause_white_24dp.png | Bin 0 -> 193 bytes .../drawable-xhdpi/ic_play_arrow_white_24dp.png | Bin 0 -> 318 bytes .../res/drawable-xhdpi/ic_shuffle_white_24dp.png | Bin 0 -> 481 bytes .../res/drawable-xhdpi/ic_skip_next_white_24dp.png | Bin 0 -> 326 bytes .../drawable-xhdpi/ic_skip_previous_white_24dp.png | Bin 0 -> 354 bytes .../res/drawable-xxhdpi/ic_pause_white_24dp.png | Bin 0 -> 215 bytes .../drawable-xxhdpi/ic_play_arrow_white_24dp.png | Bin 0 -> 399 bytes .../res/drawable-xxhdpi/ic_shuffle_white_24dp.png | Bin 0 -> 830 bytes .../drawable-xxhdpi/ic_skip_next_white_24dp.png | Bin 0 -> 408 bytes .../ic_skip_previous_white_24dp.png | Bin 0 -> 447 bytes MusicDemo/src/main/res/values-v21/styles.xml | 8 +- MusicDemo/src/main/res/values/colors.xml | 19 --- MusicDemo/src/main/res/values/styles.xml | 7 +- 21 files changed, 97 insertions(+), 95 deletions(-) create mode 100644 MusicDemo/src/main/res/drawable-hdpi/ic_pause_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-hdpi/ic_shuffle_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-hdpi/ic_skip_next_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-hdpi/ic_skip_previous_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xhdpi/ic_shuffle_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xhdpi/ic_skip_next_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xhdpi/ic_skip_previous_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xxhdpi/ic_shuffle_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_next_white_24dp.png create mode 100644 MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_previous_white_24dp.png delete mode 100644 MusicDemo/src/main/res/values/colors.xml diff --git a/MusicDemo/build.gradle b/MusicDemo/build.gradle index a0d7e19..eba452e 100644 --- a/MusicDemo/build.gradle +++ b/MusicDemo/build.gradle @@ -11,8 +11,8 @@ buildscript { apply plugin: 'android' android { - compileSdkVersion "android-L" - buildToolsVersion "21.0.0 rc1" + compileSdkVersion 21 + buildToolsVersion "21.0.0" compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 @@ -22,6 +22,4 @@ android { dependencies { - compile 'com.android.support:support-v4:18.0.+' - compile 'com.android.support:appcompat-v7:18.0.+' } diff --git a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java index 33d14c1..59b526e 100644 --- a/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java +++ b/MusicDemo/src/main/java/com/example/android/musicservicedemo/MediaNotification.java @@ -23,7 +23,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; +import android.graphics.Color; import android.media.MediaDescription; import android.media.MediaMetadata; import android.media.session.MediaController; @@ -36,6 +41,7 @@ import com.example.android.musicservicedemo.utils.BitmapHelper; import com.example.android.musicservicedemo.utils.LogHelper; import java.io.IOException; +import java.util.LinkedHashMap; /** * Keeps track of a notification and updates it automatically for a given @@ -58,6 +64,7 @@ public class MediaNotification extends BroadcastReceiver { private MediaController mController; private MediaController.TransportControls mTransportControls; private final SparseArray mIntents = new SparseArray(); + private final LinkedHashMap mAlbumArtCache; private PlaybackState mPlaybackState; private MediaMetadata mMetadata; @@ -67,6 +74,7 @@ public class MediaNotification extends BroadcastReceiver { private Notification.Action mPlayPauseAction; private String mCurrentAlbumArt; + private int mNotificationColor; private boolean mStarted = false; @@ -74,20 +82,49 @@ public class MediaNotification extends BroadcastReceiver { mService = service; updateSessionToken(); + // simple album art cache with up to 10 last accessed elements: + mAlbumArtCache = new LinkedHashMap(10, 1f, true) { + @Override + protected boolean removeEldestEntry(Entry eldest) { + return size() > 10; + } + }; + + mNotificationColor = getNotificationColor(); + mNotificationManager = (NotificationManager) mService .getSystemService(Context.NOTIFICATION_SERVICE); String pkg = mService.getPackageName(); - mIntents.put(android.R.drawable.ic_media_pause, PendingIntent.getBroadcast(mService, 100, + mIntents.put(R.drawable.ic_pause_white_24dp, PendingIntent.getBroadcast(mService, 100, new Intent(ACTION_PAUSE).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT)); - mIntents.put(android.R.drawable.ic_media_play, PendingIntent.getBroadcast(mService, 100, + mIntents.put(R.drawable.ic_play_arrow_white_24dp, PendingIntent.getBroadcast(mService, 100, new Intent(ACTION_PLAY).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT)); - mIntents.put(android.R.drawable.ic_media_previous, PendingIntent.getBroadcast(mService, 100, + mIntents.put(R.drawable.ic_skip_previous_white_24dp, PendingIntent.getBroadcast(mService, 100, new Intent(ACTION_PREV).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT)); - mIntents.put(android.R.drawable.ic_media_next, PendingIntent.getBroadcast(mService, 100, + mIntents.put(R.drawable.ic_skip_next_white_24dp, PendingIntent.getBroadcast(mService, 100, new Intent(ACTION_NEXT).setPackage(pkg), PendingIntent.FLAG_CANCEL_CURRENT)); } + protected int getNotificationColor() { + int notificationColor = 0; + String packageName = mService.getPackageName(); + try { + Context packageContext = mService.createPackageContext(packageName, 0); + ApplicationInfo applicationInfo = + mService.getPackageManager().getApplicationInfo(packageName, 0); + packageContext.setTheme(applicationInfo.theme); + Resources.Theme theme = packageContext.getTheme(); + TypedArray ta = theme.obtainStyledAttributes( + new int[] {android.R.attr.colorPrimary}); + notificationColor = ta.getColor(0, Color.DKGRAY); + ta.recycle(); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return notificationColor; + } + /** * Posts the notification and starts tracking the session to keep it * updated. The notification will automatically be removed if the session is @@ -187,61 +224,64 @@ public class MediaNotification extends BroadcastReceiver { private void updateNotificationMetadata() { LogHelper.d(TAG, "updateNotificationMetadata. mMetadata=" + mMetadata); - if (mMetadata == null) { + if (mMetadata == null || mPlaybackState == null) { return; } updatePlayPauseAction(); - boolean firstRun = false; - - if (mNotificationBuilder == null) { - firstRun = true; - - mNotificationBuilder = new Notification.Builder(mService); + mNotificationBuilder = new Notification.Builder(mService); + int playPauseActionIndex = 0; + // If skip to previous action is enabled + if ((mPlaybackState.getActions() & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0) { mNotificationBuilder - .addAction(android.R.drawable.ic_media_previous, + .addAction(R.drawable.ic_skip_previous_white_24dp, mService.getString(R.string.label_previous), - mIntents.get(android.R.drawable.ic_media_previous)) - .addAction(mPlayPauseAction) - .addAction(android.R.drawable.ic_media_next, - mService.getString(R.string.label_next), - mIntents.get(android.R.drawable.ic_media_next)) - .setStyle(new Notification.MediaStyle() - .setShowActionsInCompactView(1) // only show play/pause in compact view - .setMediaSession(mSessionToken)) - .setColor(android.R.attr.colorPrimaryDark) - .setSmallIcon(R.drawable.ic_notification) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setUsesChronometer(true); + mIntents.get(R.drawable.ic_skip_previous_white_24dp)); + playPauseActionIndex = 1; + } + + mNotificationBuilder.addAction(mPlayPauseAction); + + // If skip to next action is enabled + if ((mPlaybackState.getActions() & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) { + mNotificationBuilder.addAction(R.drawable.ic_skip_next_white_24dp, + mService.getString(R.string.label_next), + mIntents.get(R.drawable.ic_skip_next_white_24dp)); } MediaDescription description = mMetadata.getDescription(); Bitmap art = description.getIconBitmap(); + if (art == null && description.getIconUri() != null) { + // This sample assumes the iconUri will be a valid URL formatted String, but + // it can actually be any valid Android Uri formatted String. + // async fetch the album art icon + String artUrl = description.getIconUri().toString(); + art = mAlbumArtCache.get(artUrl); + if (art == null) { + fetchBitmapFromURLAsync(artUrl); + } else { + mNotificationBuilder.setLargeIcon(art); + } + } + mNotificationBuilder + .setStyle(new Notification.MediaStyle() + .setShowActionsInCompactView(playPauseActionIndex) // only show play/pause in compact view + .setMediaSession(mSessionToken)) + .setColor(mNotificationColor) + .setSmallIcon(R.drawable.ic_notification) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setOngoing(true) + .setUsesChronometer(true) .setContentTitle(description.getTitle()) .setContentText(description.getSubtitle()) .setLargeIcon(art); updateNotificationPlaybackState(); - if (firstRun) { - mService.startForeground(NOTIFICATION_ID, mNotificationBuilder.build()); - } else { - mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build()); - } - - if (art == null && description.getIconUri() != null) { - // This sample assumes the iconUri will be a valid URL formatted String, but - // it can actually be any valid Android Uri formatted String. - String albumUrl = description.getIconUri().toString(); - if (mCurrentAlbumArt == null || !mCurrentAlbumArt.equals(albumUrl)) { - mCurrentAlbumArt = albumUrl; - // async fetch the album art icon - getBitmapFromURLAsync(albumUrl); - } - } + mService.startForeground(NOTIFICATION_ID, mNotificationBuilder.build()); } private void updatePlayPauseAction() { @@ -250,10 +290,10 @@ public class MediaNotification extends BroadcastReceiver { int playPauseIcon; if (mPlaybackState.getState() == PlaybackState.STATE_PLAYING) { playPauseLabel = mService.getString(R.string.label_pause); - playPauseIcon = android.R.drawable.ic_media_pause; + playPauseIcon = R.drawable.ic_pause_white_24dp; } else { playPauseLabel = mService.getString(R.string.label_play); - playPauseIcon = android.R.drawable.ic_media_play; + playPauseIcon = R.drawable.ic_play_arrow_white_24dp; } if (mPlayPauseAction == null) { mPlayPauseAction = new Notification.Action(playPauseIcon, playPauseLabel, @@ -297,7 +337,7 @@ public class MediaNotification extends BroadcastReceiver { mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build()); } - public void getBitmapFromURLAsync(final String source) { + public void fetchBitmapFromURLAsync(final String source) { LogHelper.d(TAG, "getBitmapFromURLAsync: starting asynctask to fetch ", source); new AsyncTask() { @Override @@ -305,13 +345,12 @@ public class MediaNotification extends BroadcastReceiver { try { Bitmap bitmap = BitmapHelper.fetchAndRescaleBitmap(source, BitmapHelper.MEDIA_ART_BIG_WIDTH, BitmapHelper.MEDIA_ART_BIG_HEIGHT); + mAlbumArtCache.put(source, bitmap); if (mMetadata != null) { - MediaDescription currentDescription = mMetadata.getDescription(); + String currentSource = mMetadata.getDescription().getIconUri().toString(); // If the media is still the same, update the notification: - if (mNotificationBuilder != null && - currentDescription.getIconUri().toString().equals(source)) { + if (mNotificationBuilder != null && currentSource.equals(source)) { LogHelper.d(TAG, "getBitmapFromURLAsync: set bitmap to ", source); - mCurrentAlbumArt = source; mNotificationBuilder.setLargeIcon(bitmap); mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build()); diff --git a/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/BitmapHelper.java b/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/BitmapHelper.java index c743262..984de49 100644 --- a/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/BitmapHelper.java +++ b/MusicDemo/src/main/java/com/example/android/musicservicedemo/utils/BitmapHelper.java @@ -33,25 +33,6 @@ public class BitmapHelper { public static final int MEDIA_ART_BIG_WIDTH=128; public static final int MEDIA_ART_BIG_HEIGHT=128; - public static final Bitmap scaleBitmap(int targetW, int targetH, InputStream is) { - // Get the dimensions of the bitmap - BitmapFactory.Options bmOptions = new BitmapFactory.Options(); - bmOptions.inJustDecodeBounds = true; - BitmapFactory.decodeStream(is, null, bmOptions); - int actualW = bmOptions.outWidth; - int actualH = bmOptions.outHeight; - - // Determine how much to scale down the image - int scaleFactor = Math.min(actualW/targetW, actualH/targetH); - - // Decode the image file into a Bitmap sized to fill the View - bmOptions.inJustDecodeBounds = false; - bmOptions.inSampleSize = scaleFactor; - - Bitmap bitmap = BitmapFactory.decodeStream(is, null, bmOptions); - return bitmap; - } - public static final Bitmap scaleBitmap(int scaleFactor, InputStream is) { // Get the dimensions of the bitmap BitmapFactory.Options bmOptions = new BitmapFactory.Options(); diff --git a/MusicDemo/src/main/res/drawable-hdpi/ic_pause_white_24dp.png b/MusicDemo/src/main/res/drawable-hdpi/ic_pause_white_24dp.png new file mode 100644 index 0000000..b4bdbb5 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-hdpi/ic_pause_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png b/MusicDemo/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png new file mode 100644 index 0000000..164385d Binary files /dev/null and b/MusicDemo/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-hdpi/ic_shuffle_white_24dp.png b/MusicDemo/src/main/res/drawable-hdpi/ic_shuffle_white_24dp.png new file mode 100644 index 0000000..3eeb0ef Binary files /dev/null and b/MusicDemo/src/main/res/drawable-hdpi/ic_shuffle_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-hdpi/ic_skip_next_white_24dp.png b/MusicDemo/src/main/res/drawable-hdpi/ic_skip_next_white_24dp.png new file mode 100644 index 0000000..4eaf7ca Binary files /dev/null and b/MusicDemo/src/main/res/drawable-hdpi/ic_skip_next_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-hdpi/ic_skip_previous_white_24dp.png b/MusicDemo/src/main/res/drawable-hdpi/ic_skip_previous_white_24dp.png new file mode 100644 index 0000000..e59dedb Binary files /dev/null and b/MusicDemo/src/main/res/drawable-hdpi/ic_skip_previous_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png b/MusicDemo/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png new file mode 100644 index 0000000..14b6d17 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png b/MusicDemo/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png new file mode 100644 index 0000000..a55d199 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xhdpi/ic_shuffle_white_24dp.png b/MusicDemo/src/main/res/drawable-xhdpi/ic_shuffle_white_24dp.png new file mode 100644 index 0000000..8ce3a60 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xhdpi/ic_shuffle_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xhdpi/ic_skip_next_white_24dp.png b/MusicDemo/src/main/res/drawable-xhdpi/ic_skip_next_white_24dp.png new file mode 100644 index 0000000..f282b92 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xhdpi/ic_skip_next_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xhdpi/ic_skip_previous_white_24dp.png b/MusicDemo/src/main/res/drawable-xhdpi/ic_skip_previous_white_24dp.png new file mode 100644 index 0000000..2522877 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xhdpi/ic_skip_previous_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png b/MusicDemo/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png new file mode 100644 index 0000000..72dfa9f Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png b/MusicDemo/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png new file mode 100644 index 0000000..043acd8 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xxhdpi/ic_shuffle_white_24dp.png b/MusicDemo/src/main/res/drawable-xxhdpi/ic_shuffle_white_24dp.png new file mode 100644 index 0000000..718b6b5 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xxhdpi/ic_shuffle_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_next_white_24dp.png b/MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_next_white_24dp.png new file mode 100644 index 0000000..4fe6088 Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_next_white_24dp.png differ diff --git a/MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_previous_white_24dp.png b/MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_previous_white_24dp.png new file mode 100644 index 0000000..2c9310a Binary files /dev/null and b/MusicDemo/src/main/res/drawable-xxhdpi/ic_skip_previous_white_24dp.png differ diff --git a/MusicDemo/src/main/res/values-v21/styles.xml b/MusicDemo/src/main/res/values-v21/styles.xml index 6169d24..602ce1c 100644 --- a/MusicDemo/src/main/res/values-v21/styles.xml +++ b/MusicDemo/src/main/res/values-v21/styles.xml @@ -16,17 +16,17 @@ --> - diff --git a/MusicDemo/src/main/res/values/colors.xml b/MusicDemo/src/main/res/values/colors.xml deleted file mode 100644 index 6a5277e..0000000 --- a/MusicDemo/src/main/res/values/colors.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - #ffff0000 - diff --git a/MusicDemo/src/main/res/values/styles.xml b/MusicDemo/src/main/res/values/styles.xml index 507dc7b..3be59c1 100644 --- a/MusicDemo/src/main/res/values/styles.xml +++ b/MusicDemo/src/main/res/values/styles.xml @@ -16,8 +16,11 @@ --> - - + + + \ No newline at end of file -- cgit v1.2.3