From 4c8728c78f81fae305ececfb0f8227306f49020d Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Mon, 21 Aug 2017 23:47:47 +0200 Subject: [PATCH] Amazfit Bip: Support app icons in notifications --- .../devices/amazfitbip/AmazfitBipIcon.java | 97 +++++++++++++++++++ .../alertnotification/AlertCategory.java | 3 +- .../AlertNotificationProfile.java | 7 ++ .../profiles/alertnotification/NewAlert.java | 14 +++ .../devices/amazfitbip/AmazfitBipSupport.java | 38 ++++++-- .../AmazfitBipTextNotificationStrategy.java | 2 + 6 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/amazfitbip/AmazfitBipIcon.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/amazfitbip/AmazfitBipIcon.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/amazfitbip/AmazfitBipIcon.java new file mode 100644 index 00000000..8f952c27 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/amazfitbip/AmazfitBipIcon.java @@ -0,0 +1,97 @@ +/* Copyright (C) 2017 Andreas Shimokawa + + 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.devices.amazfitbip; + + +import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; + +public class AmazfitBipIcon { + // icons which are unsure which app they are for are suffixed with _NN + public static final int CHAT = 0; + public static final int PENGUIN_1 = 1; + public static final int MI_CHAT_2 = 2; + public static final int FACEBOOK = 3; + public static final int TWITTER = 4; + public static final int MI_APP_5 = 5; + public static final int SNAPCHAT = 6; + public static final int WHATSAPP = 7; + public static final int RED_WHITE_FIRE_8 = 8; + public static final int CHINESE_9 = 9; + public static final int ALARM_CLOCK = 10; + public static final int APP_11 = 11; + public static final int CAMERA_12 = 12; + public static final int CHAT_BLUE_13 = 13; + public static final int COW_14 = 14; + public static final int CHINESE_15 = 15; + public static final int CHINESE_16 = 16; + public static final int STAR_17 = 17; + public static final int APP_18 = 18; + public static final int CHINESE_19 = 19; + public static final int CHINESE_20 = 20; + public static final int CALENDAR = 21; + public static final int FACEBOOK_MESSENGER = 22; + public static final int WHATSAPP_CALL_23 = 23; + public static final int LINE = 24; + public static final int TELEGRAM = 25; + public static final int KAKAOTALK = 26; + public static final int SKYPE = 27; + public static final int VKONTAKTE = 28; + public static final int POKEMONGO = 29; + public static final int HANGOUTS = 30; + public static final int MI_31 = 31; + public static final int CHINESE_32 = 32; + public static final int CHINESE_33 = 33; + public static final int EMAIL = 34; + public static final int WEATHER = 35; + public static final int HR_WARNING_36 = 36; + + + public static int mapToIconId(NotificationType type) { + switch (type) { + case UNKNOWN: + return APP_11; + case CONVERSATIONS: + return CHAT; + case GENERIC_EMAIL: + return EMAIL; + case GENERIC_NAVIGATION: + return APP_11; + case GENERIC_SMS: + return CHAT; + case GENERIC_CALENDAR: + return CALENDAR; + case FACEBOOK: + return FACEBOOK; + case FACEBOOK_MESSENGER: + return FACEBOOK_MESSENGER; + case RIOT: + return CHAT; + case SIGNAL: + return CHAT_BLUE_13; + case TWITTER: + return TWITTER; + case TELEGRAM: + return TELEGRAM; + case WHATSAPP: + return WHATSAPP; + case GENERIC_ALARM_CLOCK: + return ALARM_CLOCK; + } + return APP_11; + } +} \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java index 3c7e6ae4..3af81a01 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertCategory.java @@ -37,7 +37,8 @@ public enum AlertCategory { // 10-250 reserved for future use // 251-255 defined by service specification Any(255), - Custom(-1); + Custom(-1), + CustomAmazfitBip(-6); private final int id; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java index 5f12e155..062333a5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/AlertNotificationProfile.java @@ -95,10 +95,17 @@ public class AlertNotificationProfile exten } } + public void newAlert(TransactionBuilder builder, NewAlert alert) { + newAlert(builder, alert, OverflowStrategy.TRUNCATE); + } + protected byte[] getAlertMessage(NewAlert alert, String message, int chunk) throws IOException { ByteArrayOutputStream stream = new ByteArrayOutputStream(100); stream.write(BLETypeConversions.fromUint8(alert.getCategory().getId())); stream.write(BLETypeConversions.fromUint8(alert.getNumAlerts())); + if (alert.getCategory() == AlertCategory.CustomAmazfitBip) { + stream.write(BLETypeConversions.fromUint8(alert.getCustomIcon())); + } if (message.length() > 0) { stream.write(BLETypeConversions.toUtf8s(message)); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/NewAlert.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/NewAlert.java index 66d06bf6..28a836bb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/NewAlert.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/alertnotification/NewAlert.java @@ -16,6 +16,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification; +import android.icu.util.IslamicCalendar; + /** * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.new_alert.xml&u=org.bluetooth.characteristic.new_alert.xml * @@ -47,6 +49,7 @@ public class NewAlert { private final AlertCategory category; private final int numAlerts; private final String message; + private int customIcon = -1; public NewAlert(AlertCategory category, int /*uint8*/ numAlerts, String /*utf8s*/ message) { this.category = category; @@ -54,6 +57,13 @@ public class NewAlert { this.message = message; } + public NewAlert(AlertCategory category, int /*uint8*/ numAlerts, String /*utf8s*/ message, int customIcon) { + this.category = category; + this.numAlerts = numAlerts; + this.message = message; + this.customIcon = customIcon; + } + public AlertCategory getCategory() { return category; } @@ -65,4 +75,8 @@ public class NewAlert { public String getMessage() { return message; } + + public int getCustomIcon() { + return customIcon; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index 005bbb28..2f549f01 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -16,26 +16,33 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl; +import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipIcon; import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipService; import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.AmazfitBipWeatherConditions; -import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; -import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; -import nodomain.freeyourgadget.gadgetbridge.service.devices.common.SimpleNotification; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile; +import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; public class AmazfitBipSupport extends MiBand2Support { + + private static final Logger LOG = LoggerFactory.getLogger(AmazfitBipSupport.class); + @Override public NotificationStrategy getNotificationStrategy() { return new AmazfitBipTextNotificationStrategy(this); @@ -49,8 +56,8 @@ public class AmazfitBipSupport extends MiBand2Support { } String senderOrTiltle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title); - String message = StringUtils.truncate(senderOrTiltle, 32) + "\0"; + String message = StringUtils.truncate(senderOrTiltle, 32) + "\0"; if (notificationSpec.subject != null) { message += StringUtils.truncate(notificationSpec.subject, 128) + "\n\n"; } @@ -58,9 +65,26 @@ public class AmazfitBipSupport extends MiBand2Support { message += StringUtils.truncate(notificationSpec.body, 128); } - String origin = notificationSpec.type.getGenericType(); - SimpleNotification simpleNotification = new SimpleNotification(message, BLETypeConversions.toAlertCategory(notificationSpec.type)); - performPreferredNotification(origin + " received", origin, simpleNotification, MiBand2Service.ALERT_LEVEL_MESSAGE, null); + try { + TransactionBuilder builder = performInitialized("new notification"); + AlertNotificationProfile profile = new AlertNotificationProfile(this); + profile.setMaxLength(255); // TODO: find out real limit, certainly it is more than 18 which is default + + int customIconId = AmazfitBipIcon.mapToIconId(notificationSpec.type); + + AlertCategory alertCategory = AlertCategory.CustomAmazfitBip; + + // The SMS icon for AlertCategory.SMS is unique and not available as iconId + if (notificationSpec.type == NotificationType.GENERIC_SMS) { + alertCategory = AlertCategory.SMS; + } + + NewAlert alert = new NewAlert(alertCategory, 1, message, customIconId); + profile.newAlert(builder, alert); + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Unable to send notification to Amazfit Bip", ex); + } } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java index a3554932..d7c9fac6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipTextNotificationStrategy.java @@ -30,6 +30,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2TextNotif import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; + +// This class in no longer in use except for incoming calls class AmazfitBipTextNotificationStrategy extends Mi2TextNotificationStrategy { AmazfitBipTextNotificationStrategy(MiBand2Support support) {