From 827cef203f386cb548b98a7fa9888b75478c8e20 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 17 Mar 2016 15:39:39 -0700 Subject: [PATCH] Added ColorExtractionService and ExtractedColors. - Launcher has an instance of ExtractedColors, which is loaded from LauncherProvider in onCreate() and whenever the wallpaper changes. - When the wallpaper changes, the ColorExtractionService is started in the :wallpaper-chooser process. - ColorExtractionService builds an ExtractedColors instance and saves it as a String in LauncherProvider. - When the results are saved, Launcher gets a callback through LauncherProviderChangeListener and reloads the ExtractedColors. - Whenever Launcher loads Extractecolors, it also re-colors items (currently a no-op). Change-Id: I319e2cfe0a86abcbc6bb39ef6b9fbbcad54ad743 --- AndroidManifest.xml | 5 + build.gradle | 2 + src/com/android/launcher3/Launcher.java | 17 +++ .../android/launcher3/LauncherAppState.java | 8 ++ src/com/android/launcher3/LauncherModel.java | 3 + .../android/launcher3/LauncherProvider.java | 42 +++++- .../LauncherProviderChangeListener.java | 2 + .../android/launcher3/LauncherSettings.java | 5 + src/com/android/launcher3/Utilities.java | 4 + .../dynamicui/ColorExtractionService.java | 63 +++++++++ .../launcher3/dynamicui/ExtractedColors.java | 131 ++++++++++++++++++ .../launcher3/dynamicui/ExtractionUtils.java | 75 ++++++++++ 12 files changed, 351 insertions(+), 6 deletions(-) create mode 100644 src/com/android/launcher3/dynamicui/ColorExtractionService.java create mode 100644 src/com/android/launcher3/dynamicui/ExtractedColors.java create mode 100644 src/com/android/launcher3/dynamicui/ExtractionUtils.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 418b1d2d56..80ffa43dc2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -141,6 +141,11 @@ + + + = 0 && index < mColors.length) { + mColors[index] = color; + } else { + Log.e(TAG, "Attempted to set a color at an invalid index " + index); + } + } + + /** + * Encodes {@link #mColors} as a comma-separated String. + */ + String encodeAsString() { + StringBuilder colorsStringBuilder = new StringBuilder(); + for (int color : mColors) { + colorsStringBuilder.append(color).append(COLOR_SEPARATOR); + } + return colorsStringBuilder.toString(); + } + + /** + * Decodes a comma-separated String into {@link #mColors}. + */ + void decodeFromString(String colorsString) { + String[] splitColorsString = colorsString.split(COLOR_SEPARATOR); + mColors = new int[splitColorsString.length]; + for (int i = 0; i < mColors.length; i++) { + mColors[i] = Integer.parseInt(splitColorsString[i]); + } + } + + /** + * Loads colors and wallpaper id from {@link Utilities#getPrefs(Context)}. + * These were saved there in {@link ColorExtractionService}. + */ + public void load(Context context) { + String encodedString = Utilities.getPrefs(context).getString( + ExtractionUtils.EXTRACTED_COLORS_PREFERENCE_KEY, DEFAULT_COLOR + ""); + + decodeFromString(encodedString); + } + + /** @param index must be one of the index values defined at the top of this class. */ + public int getColor(int index) { + if (index >= 0 && index < mColors.length) { + return mColors[index]; + } + return DEFAULT_COLOR; + } + + /** + * Updates colors based on the palette. + * If the palette is null, the default color is used in all cases. + */ + public void updatePalette(Palette palette) { + if (palette == null) { + for (int i = 0; i < NUM_COLOR_PROFILES; i++) { + setColorAtIndex(i, ExtractedColors.DEFAULT_COLOR); + } + } else { + setColorAtIndex(ExtractedColors.DEFAULT_INDEX, + ExtractedColors.DEFAULT_COLOR); + setColorAtIndex(ExtractedColors.VIBRANT_INDEX, + palette.getVibrantColor(ExtractedColors.DEFAULT_COLOR)); + setColorAtIndex(ExtractedColors.VIBRANT_DARK_INDEX, + palette.getDarkVibrantColor(ExtractedColors.DEFAULT_DARK)); + setColorAtIndex(ExtractedColors.VIBRANT_LIGHT_INDEX, + palette.getLightVibrantColor(ExtractedColors.DEFAULT_LIGHT)); + setColorAtIndex(ExtractedColors.MUTED_INDEX, + palette.getMutedColor(ExtractedColors.DEFAULT_COLOR)); + setColorAtIndex(ExtractedColors.MUTED_DARK_INDEX, + palette.getDarkMutedColor(ExtractedColors.DEFAULT_DARK)); + setColorAtIndex(ExtractedColors.MUTED_LIGHT_INDEX, + palette.getLightVibrantColor(ExtractedColors.DEFAULT_LIGHT)); + } + } +} diff --git a/src/com/android/launcher3/dynamicui/ExtractionUtils.java b/src/com/android/launcher3/dynamicui/ExtractionUtils.java new file mode 100644 index 0000000000..a2ff607135 --- /dev/null +++ b/src/com/android/launcher3/dynamicui/ExtractionUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.dynamicui; + +import android.app.WallpaperManager; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import com.android.launcher3.Utilities; +import com.android.wallpaperpicker.common.WallpaperManagerCompat; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Contains helper fields and methods related to extracting colors from the wallpaper. + */ +public class ExtractionUtils { + public static final String EXTRACTED_COLORS_PREFERENCE_KEY = "pref_extractedColors"; + public static final String WALLPAPER_ID_PREFERENCE_KEY = "pref_wallpaperId"; + + /** + * Extract colors in the :wallpaper-chooser process, if the wallpaper id has changed. + * When the new colors are saved in the LauncherProvider, + * Launcher will be notified in Launcher#onSettingsChanged(String, String). + */ + public static void startColorExtractionServiceIfNecessary(final Context context) { + // Run on a background thread, since the service is asynchronous anyway. + Utilities.THREAD_POOL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + if (hasWallpaperIdChanged(context)) { + context.startService(new Intent(context, ColorExtractionService.class)); + } + } + }); + } + + private static boolean hasWallpaperIdChanged(Context context) { + if (!Utilities.isNycOrAbove()) { + // TODO: update an id in sharedprefs in onWallpaperChanged broadcast, and read it here. + return false; + } + final SharedPreferences sharedPrefs = Utilities.getPrefs(context); + int wallpaperId = getWallpaperId(WallpaperManager.getInstance(context)); + int savedWallpaperId = sharedPrefs.getInt(ExtractionUtils.WALLPAPER_ID_PREFERENCE_KEY, -1); + return wallpaperId != savedWallpaperId; + } + + public static int getWallpaperId(WallpaperManager wallpaperManager) { + // TODO: use WallpaperManager#getWallpaperId(WallpaperManager.FLAG_SET_SYSTEM) directly. + try { + Method getWallpaperId = WallpaperManager.class.getMethod("getWallpaperId", int.class); + return (int) getWallpaperId.invoke(wallpaperManager, + WallpaperManagerCompat.FLAG_SET_SYSTEM); + } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { + return -1; + } + } +}