OSDN Git Service

Eleven: Make sure we have vibrant colors for all default colors
authorlinus_lee <llee@cyngn.com>
Fri, 19 Dec 2014 19:10:06 +0000 (11:10 -0800)
committerDanny Baumann <dannybaumann@web.de>
Sat, 20 Dec 2014 13:38:46 +0000 (14:38 +0100)
Change-Id: I4be163e75fc35d3b139439c504d769d17d980ace

res/values/colors.xml
src/com/cyanogenmod/eleven/MusicPlaybackService.java
src/com/cyanogenmod/eleven/appwidgets/AppWidgetLarge.java
src/com/cyanogenmod/eleven/appwidgets/AppWidgetLargeAlternate.java
src/com/cyanogenmod/eleven/appwidgets/AppWidgetSmall.java
src/com/cyanogenmod/eleven/cache/ImageFetcher.java
src/com/cyanogenmod/eleven/utils/BitmapWithColors.java [new file with mode: 0644]
src/com/cyanogenmod/eleven/widgets/LetterTileDrawable.java

index ce70bd4..43683fa 100644 (file)
     <color name="letter_tile_default_color">#cccccc</color>
     <color name="letter_tile_font_color">#ffffff</color>
     <array name="letter_tile_colors">
-        <item>#9237A2</item>
+        <item>#883397</item>
         <item>#4B498C</item>
         <item>#4E5BA7</item>
         <item>#41A4F4</item>
         <item>#B9BF45</item>
         <item>#757578</item>
     </array>
+
+    <array name="letter_tile_vibrant_dark_colors">
+        <item>#b74bc9</item>
+        <item>#6967bf</item>
+        <item>#2a315a</item>
+        <item>#07497d</item>
+        <item>#0c6c64</item>
+        <item>#415a2a</item>
+        <item>#5f6322</item>
+        <item>#505052</item>
+    </array>
 </resources>
index 2624537..5b71d86 100644 (file)
@@ -33,7 +33,6 @@ import android.database.MatrixCursor;
 import android.graphics.Bitmap;
 import android.media.AudioManager;
 import android.media.AudioManager.OnAudioFocusChangeListener;
-import android.media.MediaMetadataRetriever;
 import android.media.MediaMetadata;
 import android.media.MediaPlayer;
 import android.media.audiofx.AudioEffect;
@@ -52,7 +51,6 @@ import android.os.SystemClock;
 import android.provider.MediaStore;
 import android.provider.MediaStore.Audio.AlbumColumns;
 import android.provider.MediaStore.Audio.AudioColumns;
-import android.support.v7.graphics.Palette;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -66,7 +64,7 @@ import com.cyanogenmod.eleven.provider.MusicPlaybackState;
 import com.cyanogenmod.eleven.provider.RecentStore;
 import com.cyanogenmod.eleven.provider.SongPlayCount;
 import com.cyanogenmod.eleven.service.MusicPlaybackTrack;
-import com.cyanogenmod.eleven.utils.ApolloUtils;
+import com.cyanogenmod.eleven.utils.BitmapWithColors;
 import com.cyanogenmod.eleven.utils.Lists;
 import com.cyanogenmod.eleven.utils.SrtManager;
 
@@ -496,8 +494,7 @@ public class MusicPlaybackService extends Service {
 
     // to improve perf, instead of hitting the disk cache or file cache, store the bitmaps in memory
     private String mCachedKey;
-    private Bitmap[] mCachedBitmap = new Bitmap[2];
-    private int mCachedBitmapAccentColor = 0;
+    private BitmapWithColors[] mCachedBitmapWithColors = new BitmapWithColors[2];
 
     /**
      * Image cache
@@ -1475,7 +1472,7 @@ public class MusicPlaybackService extends Service {
             mSession.setPlaybackState(new PlaybackState.Builder()
                     .setState(playState, position(), 1.0f).build());
         } else if (what.equals(META_CHANGED) || what.equals(QUEUE_CHANGED)) {
-            Bitmap albumArt = getAlbumArt(false);
+            Bitmap albumArt = getAlbumArt(false).getBitmap();
             if (albumArt != null) {
                 // RemoteControlClient wants to recycle the bitmaps thrown at it, so we need
                 // to make sure not to hand out our cache copy
@@ -1522,7 +1519,7 @@ public class MusicPlaybackService extends Service {
         Intent nowPlayingIntent = new Intent("com.cyanogenmod.eleven.AUDIO_PLAYER")
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         PendingIntent clickIntent = PendingIntent.getActivity(this, 0, nowPlayingIntent, 0);
-        Bitmap artwork = getAlbumArt(false);
+        BitmapWithColors artwork = getAlbumArt(false);
 
         if (mNotificationPostTime == 0) {
             mNotificationPostTime = System.currentTimeMillis();
@@ -1530,7 +1527,7 @@ public class MusicPlaybackService extends Service {
 
         Notification.Builder builder = new Notification.Builder(this)
                 .setSmallIcon(R.drawable.ic_notification)
-                .setLargeIcon(artwork)
+                .setLargeIcon(artwork.getBitmap())
                 .setContentIntent(clickIntent)
                 .setContentTitle(getTrackName())
                 .setContentText(text)
@@ -1547,23 +1544,7 @@ public class MusicPlaybackService extends Service {
                         getString(R.string.accessibility_next),
                         retrievePlaybackAction(NEXT_ACTION));
 
-        if (mCachedBitmapAccentColor == 0 && artwork != null) {
-            // Generate a new Palette from the current artwork
-            final Palette p = Palette.generate(artwork);
-            if (p != null) {
-                // Check for dark vibrant colors, then vibrant
-                Palette.Swatch swatch = p.getDarkVibrantSwatch();
-                if (swatch == null) {
-                    swatch = p.getVibrantSwatch();
-                }
-                if (swatch != null) {
-                    mCachedBitmapAccentColor = swatch.getRgb();
-                }
-            }
-        }
-        if (mCachedBitmapAccentColor != 0) {
-            builder.setColor(mCachedBitmapAccentColor);
-        }
+        builder.setColor(artwork.getVibrantDarkColor());
 
         return builder.build();
     }
@@ -2680,7 +2661,7 @@ public class MusicPlaybackService extends Service {
      *                    Currently Has no impact on the artwork size if one exists
      * @return The album art for the current album.
      */
-    public Bitmap getAlbumArt(boolean smallBitmap) {
+    public BitmapWithColors getAlbumArt(boolean smallBitmap) {
         final String albumName = getAlbumName();
         final String artistName = getArtistName();
         final long albumId = getAlbumId();
@@ -2688,23 +2669,23 @@ public class MusicPlaybackService extends Service {
         final int targetIndex = smallBitmap ? 0 : 1;
 
         // if the cached key matches and we have the bitmap, return it
-        if (key.equals(mCachedKey) && mCachedBitmap[targetIndex] != null) {
-            return mCachedBitmap[targetIndex];
+        if (key.equals(mCachedKey) && mCachedBitmapWithColors[targetIndex] != null) {
+            return mCachedBitmapWithColors[targetIndex];
         }
 
         // otherwise get the artwork (or defaultartwork if none found)
-        final Bitmap bitmap = mImageFetcher.getArtwork(albumName, albumId, artistName, smallBitmap);
+        final BitmapWithColors bitmap = mImageFetcher.getArtwork(albumName,
+                albumId, artistName, smallBitmap);
 
         // if the key is different, clear the bitmaps first
         if (!key.equals(mCachedKey)) {
-            mCachedBitmap[0] = null;
-            mCachedBitmap[1] = null;
-            mCachedBitmapAccentColor = 0;
+            mCachedBitmapWithColors[0] = null;
+            mCachedBitmapWithColors[1] = null;
         }
 
         // store the new key and bitmap
         mCachedKey = key;
-        mCachedBitmap[targetIndex] = bitmap;
+        mCachedBitmapWithColors[targetIndex] = bitmap;
         return bitmap;
     }
 
index 9f726f8..1ede430 100644 (file)
@@ -114,7 +114,7 @@ public class AppWidgetLarge extends AppWidgetBase {
         final CharSequence trackName = service.getTrackName();
         final CharSequence artistName = service.getArtistName();
         final CharSequence albumName = service.getAlbumName();
-        final Bitmap bitmap = service.getAlbumArt(true);
+        final Bitmap bitmap = service.getAlbumArt(true).getBitmap();
 
         // Set the titles and artwork
         appWidgetView.setTextViewText(R.id.app_widget_large_line_one, trackName);
index f4ba43d..d40e536 100644 (file)
@@ -119,7 +119,7 @@ public class AppWidgetLargeAlternate extends AppWidgetBase {
         final CharSequence trackName = service.getTrackName();
         final CharSequence artistName = service.getArtistName();
         final CharSequence albumName = service.getAlbumName();
-        final Bitmap bitmap = service.getAlbumArt(true);
+        final Bitmap bitmap = service.getAlbumArt(true).getBitmap();
 
         // Set the titles and artwork
         appWidgetView.setTextViewText(R.id.app_widget_large_alternate_line_one, trackName);
index 7973f63..107cc7a 100644 (file)
@@ -116,7 +116,7 @@ public class AppWidgetSmall extends AppWidgetBase {
 
         final CharSequence trackName = service.getTrackName();
         final CharSequence artistName = service.getArtistName();
-        final Bitmap bitmap = service.getAlbumArt(true);
+        final Bitmap bitmap = service.getAlbumArt(true).getBitmap();
 
         // Set the titles and artwork
         if (TextUtils.isEmpty(trackName) && TextUtils.isEmpty(artistName)) {
index afa06c1..fe50c6f 100644 (file)
@@ -22,6 +22,7 @@ import android.widget.ImageView;
 import com.cyanogenmod.eleven.Config;
 import com.cyanogenmod.eleven.MusicPlaybackService;
 import com.cyanogenmod.eleven.cache.PlaylistWorkerTask.PlaylistWorkerType;
+import com.cyanogenmod.eleven.utils.BitmapWithColors;
 import com.cyanogenmod.eleven.utils.MusicUtils;
 import com.cyanogenmod.eleven.widgets.BlurScrimImage;
 import com.cyanogenmod.eleven.widgets.LetterTileDrawable;
@@ -187,8 +188,8 @@ public class ImageFetcher extends ImageWorker {
      * @param smallArtwork Get the small version of the default artwork if no artwork exists
      * @return The album art as an {@link Bitmap}
      */
-    public Bitmap getArtwork(final String albumName, final long albumId, final String artistName,
-                             boolean smallArtwork) {
+    public BitmapWithColors getArtwork(final String albumName, final long albumId,
+            final String artistName, boolean smallArtwork) {
         // Check the disk cache
         Bitmap artwork = null;
         String key = String.valueOf(albumId);
@@ -201,7 +202,7 @@ public class ImageFetcher extends ImageWorker {
             artwork = mImageCache.getArtworkFromFile(mContext, albumId);
         }
         if (artwork != null) {
-            return artwork;
+            return new BitmapWithColors(artwork);
         }
 
         return LetterTileDrawable.createDefaultBitmap(mContext, key, ImageType.ALBUM, false,
diff --git a/src/com/cyanogenmod/eleven/utils/BitmapWithColors.java b/src/com/cyanogenmod/eleven/utils/BitmapWithColors.java
new file mode 100644 (file)
index 0000000..7c76d0a
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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
+ */
+package com.cyanogenmod.eleven.utils;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.support.v7.graphics.Palette;
+
+public class BitmapWithColors {
+    private Bitmap mBitmap;
+    private int mVibrantColor;
+    private int mVibrantDarkColor;
+    private boolean mColorsLoaded = false;
+
+    public BitmapWithColors(Bitmap bitmap) {
+        mBitmap = bitmap;
+        mVibrantColor = Color.TRANSPARENT;
+        mVibrantDarkColor = Color.TRANSPARENT;
+        mColorsLoaded = false;
+    }
+
+    public BitmapWithColors(Bitmap bitmap, int vibrantColor, int vibrantDarkColor) {
+        mBitmap = bitmap;
+        mVibrantColor = vibrantColor;
+        mVibrantDarkColor = vibrantDarkColor;
+        mColorsLoaded = true;
+    }
+
+    public Bitmap getBitmap() {
+        return mBitmap;
+    }
+
+    public int getVibrantColor() {
+        loadColorsIfNeeded();
+        return mVibrantColor;
+    }
+
+    public int getVibrantDarkColor() {
+        loadColorsIfNeeded();
+        return mVibrantDarkColor;
+    }
+
+    private void loadColorsIfNeeded() {
+        synchronized (this) {
+            if (mColorsLoaded) {
+                return;
+            }
+        }
+
+        final Palette p = Palette.generate(mBitmap);
+        int vibrantColor = Color.TRANSPARENT;
+        int vibrantDarkColor = Color.TRANSPARENT;
+
+        if (p != null) {
+            Palette.Swatch swatch = p.getDarkVibrantSwatch();
+            if (swatch != null) {
+                vibrantDarkColor = swatch.getRgb();
+            }
+            swatch = p.getVibrantSwatch();
+            if (swatch != null) {
+                vibrantColor = swatch.getRgb();
+            }
+        }
+
+        if (vibrantColor == Color.TRANSPARENT && vibrantDarkColor != Color.TRANSPARENT) {
+            vibrantColor = vibrantDarkColor;
+        }
+        if (vibrantColor != Color.TRANSPARENT && vibrantDarkColor == Color.TRANSPARENT) {
+            vibrantDarkColor = vibrantColor;
+        }
+
+        synchronized (this) {
+            mColorsLoaded = true;
+            mVibrantColor = vibrantColor;
+            mVibrantDarkColor = vibrantDarkColor;
+        }
+    }
+}
index 176c216..306e998 100644 (file)
@@ -34,6 +34,7 @@ import junit.framework.Assert;
 
 import com.cyanogenmod.eleven.R;
 import com.cyanogenmod.eleven.cache.ImageWorker.ImageType;
+import com.cyanogenmod.eleven.utils.BitmapWithColors;
 import com.cyanogenmod.eleven.utils.MusicUtils;
 
 /**
@@ -48,6 +49,7 @@ public class LetterTileDrawable extends Drawable {
 
     /** Letter tile */
     private static TypedArray sColors;
+    private static TypedArray sVibrantDarkColors;
     private static int sDefaultColor;
     private static int sTileFontColor;
     private static float sLetterToTileRatio;
@@ -75,6 +77,7 @@ public class LetterTileDrawable extends Drawable {
     private static synchronized void initializeStaticVariables(final Resources res) {
         if (sColors == null) {
             sColors = res.obtainTypedArray(R.array.letter_tile_colors);
+            sVibrantDarkColors = res.obtainTypedArray(R.array.letter_tile_vibrant_dark_colors);
             sDefaultColor = res.getColor(R.color.letter_tile_default_color);
             sTileFontColor = res.getColor(R.color.letter_tile_font_color);
             sLetterToTileRatio = res.getFraction(R.dimen.letter_to_tile_ratio, 1, 1);
@@ -173,17 +176,38 @@ public class LetterTileDrawable extends Drawable {
     }
 
     /**
+     * @return the corresponding index in the color palette based on the identifier
+     */
+    private static int getColorIndex(final String identifier) {
+        if (TextUtils.isEmpty(identifier)) {
+            return -1;
+        }
+
+        return Math.abs(identifier.hashCode()) % sColors.length();
+    }
+
+    /**
      * Returns a deterministic color based on the provided contact identifier string.
      */
     private static int pickColor(final String identifier) {
-        if (TextUtils.isEmpty(identifier)) {
+        final int idx = getColorIndex(identifier);
+        if (idx == -1) {
             return sDefaultColor;
         }
-        // String.hashCode() implementation is not supposed to change across java versions, so
-        // this should guarantee the same email address always maps to the same color.
-        // The email should already have been normalized by the ContactRequest.
-        final int color = Math.abs(identifier.hashCode()) % sColors.length();
-        return sColors.getColor(color, sDefaultColor);
+
+        return sColors.getColor(idx, sDefaultColor);
+    }
+
+    /**
+     * Returns the vibrant matching color based on the provided contact identifier string.
+     */
+    private static int pickVibrantDarkColor(final String identifier) {
+        final int idx = getColorIndex(identifier);
+        if (idx == -1) {
+            return sDefaultColor;
+        }
+
+        return sVibrantDarkColors.getColor(idx, sDefaultColor);
     }
 
     /**
@@ -309,8 +333,8 @@ public class LetterTileDrawable extends Drawable {
      * @param smallArtwork true if you want to draw a smaller version of the default bitmap for
      *                     perf/memory reasons
      */
-    public static Bitmap createDefaultBitmap(Context context, String identifier, ImageType type, 
-                                             boolean isCircle, boolean smallArtwork) {
+    public static BitmapWithColors createDefaultBitmap(Context context, String identifier,
+            ImageType type, boolean isCircle, boolean smallArtwork) {
         initializeStaticVariables(context.getResources());
         
         identifier = MusicUtils.getTrimmedName(identifier);
@@ -324,8 +348,11 @@ public class LetterTileDrawable extends Drawable {
                 defaultBitmap.getHeight(), defaultBitmap.getConfig());
         Canvas canvas = new Canvas(createdBitmap);
 
+        int color = pickColor(identifier);
+        int vibrantDarkColor = pickVibrantDarkColor(identifier);
+
         Paint paint = new Paint();
-        paint.setColor(pickColor(identifier));
+        paint.setColor(color);
 
         final int minDimension = Math.min(bounds.width(), bounds.height());
 
@@ -339,6 +366,6 @@ public class LetterTileDrawable extends Drawable {
         drawBitmap(defaultBitmap, defaultBitmap.getWidth(), defaultBitmap.getHeight(), canvas,
                 bounds, 1, 0, paint);
 
-        return createdBitmap;
+        return new BitmapWithColors(createdBitmap, color, vibrantDarkColor);
     }
 }