From 6ec15551781046a389bf695f68b219a8ed6995db Mon Sep 17 00:00:00 2001 From: Frank Slezak Date: Tue, 19 Sep 2017 04:24:31 -0700 Subject: [PATCH] Add support for dynamic Pebble background colors (#819) Pebble: Add support for dynamic Pebble background colors - Add a couple additional icon types - Add Lighthouse (currently unused) - Add Transit (public transportation app) - Tweak the colors on existing icon types - Implement logic to grab primary (vibrant) color from app logo - The color will be used when displaying a notification for an app that does not have any configs bound to it. - Alter NotificationType to support a color (named pebbleColor) - Alter the Pebble notification poster to listen to the color from the notification - Alter the DeviceCommunicationService to allow for color passthrough. - Add logic to convert HEX or Integer representations of RGB888 colors to Pebble RGB222 format. - make the package name retrieved lowercase. Fixes: #815 --- app/build.gradle | 1 + .../activities/DebugActivity.java | 1 + .../externalevents/NotificationListener.java | 68 +++++++++++++++---- .../gadgetbridge/impl/GBDeviceService.java | 3 +- .../model/AppNotificationType.java | 3 + .../gadgetbridge/model/DeviceService.java | 1 + .../gadgetbridge/model/NotificationSpec.java | 10 +++ .../gadgetbridge/model/NotificationType.java | 4 +- .../service/DeviceCommunicationService.java | 2 + .../devices/pebble/PebbleProtocol.java | 14 ++-- .../gadgetbridge/util/BitmapUtil.java | 49 +++++++++++++ .../gadgetbridge/util/PebbleUtils.java | 27 ++++++++ .../gadgetbridge/test/PebbleUtilsTest.java | 54 +++++++++++++++ 13 files changed, 218 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BitmapUtil.java create mode 100644 app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/PebbleUtilsTest.java diff --git a/app/build.gradle b/app/build.gradle index c0e7d68c2..10ae381c1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,6 +70,7 @@ dependencies { compile 'com.android.support:support-v4:25.3.1' compile 'com.android.support:gridlayout-v7:25.3.1' compile 'com.android.support:design:25.3.1' + compile 'com.android.support:palette-v7:25.3.1' compile 'com.github.tony19:logback-android-classic:1.1.1-6' compile 'org.slf4j:slf4j-api:1.7.7' compile 'com.github.PhilJay:MPAndroidChart:v3.0.2' diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java index 03e3cecdf..198b98ef1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java @@ -126,6 +126,7 @@ public class DebugActivity extends AbstractGBActivity { notificationSpec.sender = testString; notificationSpec.subject = testString; notificationSpec.type = NotificationType.values()[sendTypeSpinner.getSelectedItemPosition()]; + notificationSpec.pebbleColor = notificationSpec.type.color; notificationSpec.id = -1; GBApplication.deviceService().onNotification(notificationSpec); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index 6b77850ff..48ee2ca32 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -28,6 +28,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.Drawable; import android.media.MediaMetadata; import android.media.session.PlaybackState; import android.os.Bundle; @@ -42,21 +45,26 @@ import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.support.v7.app.NotificationCompat; +import android.support.v7.graphics.Palette; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; +import java.util.Objects; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor; import nodomain.freeyourgadget.gadgetbridge.model.AppNotificationType; import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService; +import nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil; import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue; +import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class NotificationListener extends NotificationListenerService { @@ -192,7 +200,7 @@ public class NotificationListener extends NotificationListenerService { return; } - String source = sbn.getPackageName(); + String source = sbn.getPackageName().toLowerCase(); Notification notification = sbn.getNotification(); NotificationSpec notificationSpec = new NotificationSpec(); notificationSpec.id = (int) sbn.getPostTime(); //FIMXE: a truly unique id would be better @@ -211,6 +219,9 @@ public class NotificationListener extends NotificationListenerService { boolean preferBigText = false; + // Get the app ID that generated this notification. For now only used by pebble color, but may be more useful later. + notificationSpec.sourceAppId = source; + notificationSpec.type = AppNotificationType.getInstance().get(source); if (source.startsWith("com.fsck.k9")) { @@ -221,6 +232,9 @@ public class NotificationListener extends NotificationListenerService { notificationSpec.type = NotificationType.UNKNOWN; } + // Get color + notificationSpec.pebbleColor = getPebbleColorForNotification(notificationSpec); + LOG.info("Processing notification " + notificationSpec.id + " from source " + source + " with flags: " + notification.flags); dissectNotificationTo(notification, notificationSpec, preferBigText); @@ -379,13 +393,9 @@ public class NotificationListener extends NotificationListenerService { return true; } - if (shouldIgnoreSource(sbn.getPackageName())) - return true; + return shouldIgnoreSource(sbn.getPackageName()) || shouldIgnoreNotification( + sbn.getNotification()); - if (shouldIgnoreNotification(sbn.getNotification())) - return true; - - return false; } private boolean shouldIgnoreSource(String source) { @@ -442,12 +452,46 @@ public class NotificationListener extends NotificationListenerService { } } - if ((notification.flags & Notification.FLAG_ONGOING_EVENT) == Notification.FLAG_ONGOING_EVENT) { -// LOG.info("Not forwarding notification, FLAG_ONGOING_EVENT is set. Notification flags: " + notification.flags); - return true; - } + return (notification.flags & Notification.FLAG_ONGOING_EVENT) == Notification.FLAG_ONGOING_EVENT; - return false; } + + /** + * Get the notification color that should be used for this Pebble notification. + * + * Note that this method will *not* edit the NotificationSpec passed in. It will only evaluate the PebbleColor. + * + * See Issue #815 on GitHub to see how notification colors are set. + * + * @param notificationSpec The NotificationSpec to read from. + * @return Returns a PebbleColor that best represents this notification. + */ + private byte getPebbleColorForNotification(NotificationSpec notificationSpec) { + String appId = notificationSpec.sourceAppId; + NotificationType existingType = notificationSpec.type; + + // If the notification type is known, return the associated color. + if (existingType != NotificationType.UNKNOWN) { + return existingType.color; + } + + // Otherwise, we go and attempt to find the color from the app icon. + Drawable icon; + try { + icon = getApplicationContext().getPackageManager().getApplicationIcon(appId); + Objects.requireNonNull(icon); + } catch (Exception ex) { + // If we can't get the icon, we go with the default defined above. + LOG.warn("Could not get icon for AppID " + appId, ex); + return PebbleColor.IslamicGreen; + } + + Bitmap bitmapIcon = BitmapUtil.convertDrawableToBitmap(icon); + int iconPrimaryColor = new Palette.Builder(bitmapIcon) + .generate() + .getVibrantColor(Color.parseColor("#aa0000")); + + return PebbleUtils.getPebbleColor(iconPrimaryColor); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java index 6fd8f550c..fff316d9c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -141,7 +141,8 @@ public class GBDeviceService implements DeviceService { .putExtra(EXTRA_NOTIFICATION_BODY, notificationSpec.body) .putExtra(EXTRA_NOTIFICATION_ID, notificationSpec.id) .putExtra(EXTRA_NOTIFICATION_TYPE, notificationSpec.type) - .putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName); + .putExtra(EXTRA_NOTIFICATION_SOURCENAME, notificationSpec.sourceName) + .putExtra(EXTRA_NOTIFICATION_PEBBLE_COLOR, notificationSpec.pebbleColor); invokeService(intent); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java index 8b8ede180..9ea8021f0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java @@ -135,6 +135,9 @@ public class AppNotificationType extends HashMap { // Slack put("com.slack", NotificationType.SLACK); + + // Transit + put("com.thetransitapp.droid", NotificationType.TRANSIT); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java index 033422a33..2e2a1a6a2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java @@ -73,6 +73,7 @@ public interface DeviceService extends EventHandler { String EXTRA_NOTIFICATION_SUBJECT = "notification_subject"; String EXTRA_NOTIFICATION_TITLE = "notification_title"; String EXTRA_NOTIFICATION_TYPE = "notification_type"; + String EXTRA_NOTIFICATION_PEBBLE_COLOR = "notification_pebble_color"; String EXTRA_FIND_START = "find_start"; String EXTRA_VIBRATION_INTENSITY = "vibration_intensity"; String EXTRA_CALL_COMMAND = "call_command"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java index ce5f3da81..83f31e92b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationSpec.java @@ -29,4 +29,14 @@ public class NotificationSpec { public NotificationType type; public String sourceName; public String[] cannedReplies; + + /** + * The application that generated the notification. + */ + public String sourceAppId; + + /** + * The color that should be assigned to this notification when displayed on a Pebble + */ + public byte pebbleColor; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java index aed2a951f..be716fc76 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NotificationType.java @@ -23,7 +23,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID; public enum NotificationType { // TODO: this this pebbleism needs to be moved somewhere else - UNKNOWN(PebbleIconID.NOTIFICATION_GENERIC, PebbleColor.Red), + UNKNOWN(PebbleIconID.NOTIFICATION_GENERIC, PebbleColor.DarkCandyAppleRed), AMAZON(PebbleIconID.NOTIFICATION_AMAZON, PebbleColor.ChromeYellow), BBM(PebbleIconID.NOTIFICATION_BLACKBERRY_MESSENGER, PebbleColor.DarkGray), @@ -46,6 +46,7 @@ public enum NotificationType { INSTAGRAM(PebbleIconID.NOTIFICATION_INSTAGRAM, PebbleColor.CobaltBlue), KAKAO_TALK(PebbleIconID.NOTIFICATION_KAKAOTALK, PebbleColor.Yellow), KIK(PebbleIconID.NOTIFICATION_KIK, PebbleColor.IslamicGreen), + LIGHTHOUSE(PebbleIconID.NOTIFICATION_LIGHTHOUSE, PebbleColor.PictonBlue), // ??? - No idea what this is, but it works. LINE(PebbleIconID.NOTIFICATION_LINE, PebbleColor.IslamicGreen), LINKEDIN(PebbleIconID.NOTIFICATION_LINKEDIN, PebbleColor.CobaltBlue), MAILBOX(PebbleIconID.NOTIFICATION_MAILBOX, PebbleColor.VividCerulean), @@ -56,6 +57,7 @@ public enum NotificationType { SLACK(PebbleIconID.NOTIFICATION_SLACK, PebbleColor.Folly), SNAPCHAT(PebbleIconID.NOTIFICATION_SNAPCHAT, PebbleColor.Icterine), TELEGRAM(PebbleIconID.NOTIFICATION_TELEGRAM, PebbleColor.VividCerulean), + TRANSIT(PebbleIconID.LOCATION, PebbleColor.JaegerGreen), TWITTER(PebbleIconID.NOTIFICATION_TWITTER, PebbleColor.BlueMoon), VIBER(PebbleIconID.NOTIFICATION_VIBER, PebbleColor.VividViolet), WECHAT(PebbleIconID.NOTIFICATION_WECHAT, PebbleColor.KellyGreen), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index 73eacc58f..e6f842688 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -137,6 +137,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUS import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_BODY; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_FLAGS; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ID; +import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PEBBLE_COLOR; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_PHONENUMBER; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SENDER; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_SOURCENAME; @@ -342,6 +343,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere notificationSpec.body = intent.getStringExtra(EXTRA_NOTIFICATION_BODY); notificationSpec.sourceName = intent.getStringExtra(EXTRA_NOTIFICATION_SOURCENAME); notificationSpec.type = (NotificationType) intent.getSerializableExtra(EXTRA_NOTIFICATION_TYPE); + notificationSpec.pebbleColor = (byte) intent.getSerializableExtra(EXTRA_NOTIFICATION_PEBBLE_COLOR); notificationSpec.id = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1); notificationSpec.flags = intent.getIntExtra(EXTRA_NOTIFICATION_FLAGS, 0); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index 86e303fd6..27b1f3481 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -496,10 +496,13 @@ public class PebbleProtocol extends GBDeviceProtocol { if (mFwMajor >= 3) { // 3.x notification - return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, notificationSpec.sourceName, hasHandle, notificationSpec.type, notificationSpec.cannedReplies); + return encodeBlobdbNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, + notificationSpec.sourceName, hasHandle, notificationSpec.type, notificationSpec.pebbleColor, + notificationSpec.cannedReplies); } else if (mForceProtocol || notificationSpec.type != NotificationType.GENERIC_EMAIL) { // 2.x notification - return encodeExtensibleNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, notificationSpec.sourceName, hasHandle, notificationSpec.cannedReplies); + return encodeExtensibleNotification(id, (int) (ts & 0xffffffffL), title, subtitle, notificationSpec.body, + notificationSpec.sourceName, hasHandle, notificationSpec.cannedReplies); } else { // 1.x notification on FW 2.X String[] parts = {title, notificationSpec.body, ts.toString(), subtitle}; @@ -920,7 +923,9 @@ public class PebbleProtocol extends GBDeviceProtocol { return encodeBlobdb(uuid, BLOBDB_INSERT, BLOBDB_PIN, buf.array()); } - private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName, boolean hasHandle, NotificationType notificationType, String[] cannedReplies) { + private byte[] encodeBlobdbNotification(int id, int timestamp, String title, String subtitle, String body, String sourceName, + boolean hasHandle, NotificationType notificationType, byte backgroundColor, + String[] cannedReplies) { final short NOTIFICATION_PIN_LENGTH = 46; final short ACTION_LENGTH_MIN = 10; @@ -931,7 +936,6 @@ public class PebbleProtocol extends GBDeviceProtocol { } int icon_id = notificationType.icon; - byte color_id = notificationType.color; // Calculate length first byte actions_count; @@ -1021,7 +1025,7 @@ public class PebbleProtocol extends GBDeviceProtocol { buf.put((byte) 28); // background_color buf.putShort((short) 1); // length of int - buf.put(color_id); + buf.put(backgroundColor); // dismiss action buf.put(dismiss_action_id); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BitmapUtil.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BitmapUtil.java new file mode 100644 index 000000000..681648ece --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/BitmapUtil.java @@ -0,0 +1,49 @@ +/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ + +package nodomain.freeyourgadget.gadgetbridge.util; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; + +public class BitmapUtil { + + /** + * Get a Bitmap from any given Drawable. + * + * Note that this code will fail if the drawable is 0x0. + * + * @param drawable A Drawable to convert. + * @return A Bitmap representing the drawable. + */ + public static Bitmap convertDrawableToBitmap(Drawable drawable) { + // If whoever made this drawable decided to be nice to us... + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PebbleUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PebbleUtils.java index 70c13e45a..c25704a41 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PebbleUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PebbleUtils.java @@ -16,6 +16,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.util; +import android.graphics.Color; + public class PebbleUtils { public static String getPlatformName(String hwRev) { String platformName; @@ -63,4 +65,29 @@ public class PebbleUtils { String platformName = getPlatformName(hwRev); return !"aplite".equals(platformName); } + + /** + * Get the closest Pebble-compatible color from the associated Android Color Integer. + * @param color An Android Color Integer to convert + * @return A byte representing the closest Pebble color. + */ + public static byte getPebbleColor(int color) { + // 85 here is determined by dividing 255 by 3, or reducing an 8-bit color to a 2-bit color. (2^3 = 8) + + int colorRed = ((color >> 16) & 0xFF) / 85; + int colorGreen = ((color >> 8) & 0xFF) / 85; + int colorBlue = (color & 0xFF) / 85; + + // Bit shifting, woo! + return (byte) ((0b11 << 6) | ((colorRed & 0b11) << 4) | ((colorGreen & 0b11) << 2) | (colorBlue & 0b11)); + } + + /** + * Get the closest Pebble-compatible color from the associated Hex string. + * @param colorHex A Hex-formatted string (#FFDD00) to convert. + * @return A byte representing the closest Pebble color. + */ + public static byte getPebbleColor(String colorHex) { + return getPebbleColor(Color.parseColor(colorHex)); + } } diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/PebbleUtilsTest.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/PebbleUtilsTest.java new file mode 100644 index 000000000..6fce5d43f --- /dev/null +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/PebbleUtilsTest.java @@ -0,0 +1,54 @@ +package nodomain.freeyourgadget.gadgetbridge.test; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor; +import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils; + +import static org.junit.Assert.assertEquals; + +public class PebbleUtilsTest extends TestBase { + @Test + public void testHexToPebbleColorConversion() { + Map testCases = new HashMap<>(); + + testCases.put("#000000", PebbleColor.Black); + testCases.put("#ffffff", PebbleColor.White); + testCases.put("#00ff00", PebbleColor.Green); + + testCases.put("#452435", PebbleColor.Black); + testCases.put("#334afd", PebbleColor.DukeBlue); + testCases.put("#ccb75c", PebbleColor.Brass); + testCases.put("#1b1c94", PebbleColor.OxfordBlue); + testCases.put("#90f892", PebbleColor.MayGreen); + testCases.put("#ff7301", PebbleColor.Orange); + + testCases.put("#00aa00", PebbleColor.IslamicGreen); + + for (String colorKey : testCases.keySet()) { + byte evaluatedColor = PebbleUtils.getPebbleColor(colorKey); + assertEquals("Color " + colorKey + " failed to translate properly!", + testCases.get(colorKey).byteValue(), evaluatedColor); + } + } + + @Test + public void testIntToPebbleColorConversion() { + Map testCases = new HashMap<>(); + + testCases.put(0x000000, PebbleColor.Black); + testCases.put(0xffffff, PebbleColor.White); + testCases.put(0x00ff00, PebbleColor.Green); + + testCases.put(0x00aa00, PebbleColor.IslamicGreen); + + for (int colorKey : testCases.keySet()) { + byte evaluatedColor = PebbleUtils.getPebbleColor(colorKey); + assertEquals("Color " + Integer.toHexString(colorKey) + " failed to translate properly!", + testCases.get(colorKey).byteValue(), evaluatedColor); + } + } +}