From 735f27d5bf3c09eaca8664d44e9d8ce838e7c77a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Jun 2023 08:47:10 +0100 Subject: [PATCH] Add Navigation handling to Bangle.js Add extra 'ETA' field to NavigationInfoSpec Allow Local Notifications from Google Maps to be parsed into NavigationInfoSpec by GoogleMapsNotificationHandler Moved notification handling after blacklist check as per https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3136#issuecomment-920095 Ensure we don't create a nav message for 'Location Shared with you' messages. Recognise 'ft' as a distance unit and convert accordingly Google Maps navigation: Adding new recognised icons, and removing warnings/errors from file --- .../devices/banglejs/BangleJSCoordinator.java | 5 + .../externalevents/NotificationListener.java | 8 + .../GoogleMapsNotificationHandler.java | 757 ++++++++++++++++++ .../gadgetbridge/impl/GBDeviceService.java | 3 +- .../gadgetbridge/model/DeviceService.java | 1 + .../model/NavigationInfoSpec.java | 8 +- .../service/DeviceCommunicationService.java | 2 + .../banglejs/BangleJSDeviceSupport.java | 23 + 8 files changed, 804 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/notifications/GoogleMapsNotificationHandler.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java index 9e52cafe7..d5202d83b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java @@ -205,4 +205,9 @@ public class BangleJSCoordinator extends AbstractBLEDeviceCoordinator { for (int i=0; i knownImages; + + public GoogleMapsNotificationHandler() { + knownImages = new ArrayList<>(); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_CONTINUE, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000001000000000000000, + 0b00000000000000011100000000000000, + 0b00000000000000111110000000000000, + 0b00000000000011111111000000000000, + 0b00000000000111111111100000000000, + 0b00000000001111111111110000000000, + 0b00000000011111111111111000000000, + 0b00000000111110111101111100000000, + 0b00000000111100111100111100000000, + 0b00000000011000111100011100000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_CONTINUE, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000001000000000000000, + 0b00000000000000011100000000000000, + 0b00000000000000111110000000000000, + 0b00000000000011111111000000000000, + 0b00000000000111111111100000000000, + 0b00000000001111111111110000000000, + 0b00000000011111111111111000000000, + 0b00000000111110111101111100000000, + 0b00000000111100111100111100000000, + 0b00000000011000111100011100000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_TURN_LEFT, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000001100000000000000000000, + 0b00000000011110000000000000000000, + 0b00000000111110000000000000000000, + 0b00000001111100000000000000000000, + 0b00000011111000000000000000000000, + 0b00000111110000000000000000000000, + 0b00001111111111111111111110000000, + 0b00011111111111111111111111100000, + 0b00001111111111111111111111110000, + 0b00000111100000000000000111111000, + 0b00000011110000000000000001111000, + 0b00000011111000000000000000111000, + 0b00000001111100000000000000111000, + 0b00000000111110000000000000111000, + 0b00000000011110000000000000111000, + 0b00000000000100000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000111000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_TURN_RIGHT, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000110000000000, + 0b00000000000000000001111000000000, + 0b00000000000000000001111100000000, + 0b00000000000000000000111110000000, + 0b00000000000000000000011111000000, + 0b00000000000000000000001111100000, + 0b00000001111111111111111111110000, + 0b00000111111111111111111111111000, + 0b00001111111111111111111111111000, + 0b00001111100000000000000111110000, + 0b00011110000000000000001111100000, + 0b00011100000000000000011111000000, + 0b00011100000000000000111110000000, + 0b00011100000000000001111100000000, + 0b00011100000000000001111000000000, + 0b00011100000000000000100000000000, + 0b00011100000000000000000000000000, + 0b00011100000000000000000000000000, + 0b00011100000000000000000000000000, + 0b00011100000000000000000000000000, + 0b00011100000000000000000000000000, + 0b00011100000000000000000000000000, + 0b00011100000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_TURN_LEFT_SLIGHTLY, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000111111111111000000000000, + 0b00000000111111111111000000000000, + 0b00000000111111111111000000000000, + 0b00000000111111000000000000000000, + 0b00000000111111100000000000000000, + 0b00000000111111110000000000000000, + 0b00000000111011111000000000000000, + 0b00000000111001111100000000000000, + 0b00000000111000111110000000000000, + 0b00000000111000011111000000000000, + 0b00000000111000001111100000000000, + 0b00000000111000000111110000000000, + 0b00000000000000000011111000000000, + 0b00000000000000000001111000000000, + 0b00000000000000000000111100000000, + 0b00000000000000000000011100000000, + 0b00000000000000000000011110000000, + 0b00000000000000000000011110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_TURN_RIGHT_SLIGHTLY, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000011111111111100000000, + 0b00000000000011111111111100000000, + 0b00000000000011111111111100000000, + 0b00000000000000000011111100000000, + 0b00000000000000000111111100000000, + 0b00000000000000001111111100000000, + 0b00000000000000011111011100000000, + 0b00000000000000111110011100000000, + 0b00000000000001111100011100000000, + 0b00000000000011111000011100000000, + 0b00000000000111110000011100000000, + 0b00000000001111100000011100000000, + 0b00000000011111000000000000000000, + 0b00000000011110000000000000000000, + 0b00000000111100000000000000000000, + 0b00000000111000000000000000000000, + 0b00000001111000000000000000000000, + 0b00000001111000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_FINISH, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000011111111000000000000, + 0b00000000001111111111110000000000, + 0b00000000011111000011111000000000, + 0b00000000111100000000111100000000, + 0b00000001111000000000011110000000, + 0b00000001110000000000001110000000, + 0b00000011100000000000000111000000, + 0b00000011100000000000000111000000, + 0b00000011000000111100000011000000, + 0b00000111000001111110000011100000, + 0b00000111000001111110000011100000, + 0b00000111000000111100000011100000, + 0b00000111000000111100000011100000, + 0b00000011000000000000000011000000, + 0b00000011100000000000000111000000, + 0b00000011100000000000000111000000, + 0b00000001110000000000001110000000, + 0b00000000111000000000011100000000, + 0b00000000111100000000111100000000, + 0b00000000011100000000111000000000, + 0b00000000001110000001110000000000, + 0b00000000000111000011100000000000, + 0b00000000000011111111000000000000, + 0b00000000000001111110000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000011000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_FINISH, new int[]{ + 0b00000000000000000000000000000000, + 0b00000000111000000000000000000000, + 0b00000111111110000000000000000000, + 0b00001111111111100000000000000000, + 0b00011110000011110000000000000000, + 0b00111100000001110000000000000000, + 0b00111000000000111000000000000000, + 0b00110000010000111000000000000000, + 0b01110000111000011000000000000000, + 0b01110001111000011000000000000000, + 0b01110000111000011000000000000000, + 0b00110000000000111000000000000000, + 0b00111000000000111000000000000000, + 0b00111000000001110000000000000000, + 0b00011100000001110000000000000000, + 0b00011100000011100011000111100000, + 0b00001110000011100111000111100000, + 0b00001111000111000111111111110000, + 0b00000111001111001111111111110000, + 0b00000011101110011111111111110000, + 0b00000011111100011111000111110000, + 0b00000001111000111111000111111000, + 0b00000000111000111111000111111000, + 0b00000000010001111111111111111000, + 0b00000000000001111111111111111100, + 0b00000000000001111111000111111100, + 0b00000000000011111111000111111100, + 0b00000000000011111111000111111110, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_LEFT, new int[]{ + 0b000000000000000000000000000000000, + 0b000000000000000000000000000000000, + 0b000000000000000000000000000000000, + 0b000000000000000000000000000000000, + 0b000000001111111111100000000000000, + 0b000000001111111111110000000000000, + 0b000000001111111111110000000000000, + 0b000000001111100000000000000000000, + 0b000000001111110000000000000000000, + 0b000000001111111000000000000000000, + 0b000000001111111100000000000000000, + 0b000000001110111110000000000000000, + 0b000000001110011111000000000000000, + 0b000000001110001111100000000000000, + 0b000000001110001111000000000000000, + 0b000000001110011110000000000000000, + 0b000000000000011110000000000000000, + 0b000000000000011100000000000000000, + 0b000000000000011100000000000000000, + 0b000000000000011110000000000000000, + 0b000000000000011110000000000000000, + 0b000000000000001111000000000000000, + 0b000000000000000111111100000000000, + 0b000000000000000111111100000000000, + 0b000000000000000001111100000000000, + 0b000000000000000000011100000000000, + 0b000000000000000000011100000000000, + 0b000000000000000000011100000000000, + 0b000000000000000000000000000000000, + 0b000000000000000000000000000000000, + 0b000000000000000000000000000000000, + 0b000000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_RIGHT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000111111111110000000, + 0b00000000000001111111111110000000, + 0b00000000000001111111111110000000, + 0b00000000000000000000111110000000, + 0b00000000000000000001111110000000, + 0b00000000000000000011111110000000, + 0b00000000000000000111111110000000, + 0b00000000000000001111101110000000, + 0b00000000000000011111001110000000, + 0b00000000000000111110001110000000, + 0b00000000000000011110001110000000, + 0b00000000000000001111001110000000, + 0b00000000000000001111000000000000, + 0b00000000000000000111000000000000, + 0b00000000000000000111000000000000, + 0b00000000000000001111000000000000, + 0b00000000000000001111000000000000, + 0b00000000000000011110000000000000, + 0b00000000000111111100000000000000, + 0b00000000000111111100000000000000, + 0b00000000000111110000000000000000, + 0b00000000000111000000000000000000, + 0b00000000000111000000000000000000, + 0b00000000000111000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_STRAIGHT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000011000000000000000, + 0b00000000000000111100000000000000, + 0b00000000000001111110000000000000, + 0b00000000000011111111000000000000, + 0b00000000000111111111100000000000, + 0b00000000001111111111110000000000, + 0b00000000011110111101111000000000, + 0b00000000111100111100111100000000, + 0b00000000111000111100011100000000, + 0b00000000000000111100000000000000, + 0b00000000000011111100000000000000, + 0b00000000000111111100000000000000, + 0b00000000001111111100000000000000, + 0b00000000011111000000000000000000, + 0b00000000011110000000000000000000, + 0b00000000011100000000000000000000, + 0b00000000011100000000000000000000, + 0b00000000011100000000000000000000, + 0b00000000011100000000000000000000, + 0b00000000011110000000000000000000, + 0b00000000011111000000000000000000, + 0b00000000001111111100000000000000, + 0b00000000000111111100000000000000, + 0b00000000000011111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_STRAIGHT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000011000000000000000, + 0b00000000000000111100000000000000, + 0b00000000000001111110000000000000, + 0b00000000000011111111000000000000, + 0b00000000000111111111100000000000, + 0b00000000001111111111110000000000, + 0b00000000011110111101111000000000, + 0b00000000111100111100111100000000, + 0b00000000111000111100011100000000, + 0b00000000000000111100000000000000, + 0b00000000000000111111000000000000, + 0b00000000000000111111100000000000, + 0b00000000000000111111110000000000, + 0b00000000000000000011111000000000, + 0b00000000000000000001111000000000, + 0b00000000000000000000111000000000, + 0b00000000000000000000111000000000, + 0b00000000000000000000111000000000, + 0b00000000000000000000111000000000, + 0b00000000000000000001111000000000, + 0b00000000000000000011111000000000, + 0b00000000000000111111110000000000, + 0b00000000000000111111100000000000, + 0b00000000000000111111000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000111100000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_LEFT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000011000000000000000000000, + 0b00000000111100000000000000000000, + 0b00000001111100000000000000000000, + 0b00000011111000000000000000000000, + 0b00000111110000000000000000000000, + 0b00001111100000000000000000000000, + 0b00011111111111111110000000000000, + 0b00111111111111111110000000000000, + 0b00111111111111111111000000000000, + 0b00011111111111111111000000000000, + 0b00001111100000001111000000000000, + 0b00000111110000000111110000000000, + 0b00000011111000000011111110000000, + 0b00000001111100000011111111000000, + 0b00000000111100000000111110000000, + 0b00000000011000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_RIGHT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000011000000000, + 0b00000000000000000000111100000000, + 0b00000000000000000000111110000000, + 0b00000000000000000000011111000000, + 0b00000000000000000000001111100000, + 0b00000000000000000000000111110000, + 0b00000000000001111111111111111000, + 0b00000000000001111111111111111100, + 0b00000000000011111111111111111100, + 0b00000000000011111111111111111000, + 0b00000000000011110000000111110000, + 0b00000000001111100000001111100000, + 0b00000001111111000000011111000000, + 0b00000011111111000000111110000000, + 0b00000001111100000000111100000000, + 0b00000001110000000000011000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_LEFT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000111111111111000000000000000, + 0b00000111111111111000000000000000, + 0b00000111111111111000000000000000, + 0b00000111111100000000000000000000, + 0b00000111111100000000000000000000, + 0b00000111111110000000000000000000, + 0b00000111111111000000000000000000, + 0b00000111101111101111111000000000, + 0b00000111100111111111111100000000, + 0b00000111100011111111111110000000, + 0b00000111100001111100011111000000, + 0b00000011000000110000001111000000, + 0b00000000000000000000000111100000, + 0b00000000000000000000000111100000, + 0b00000000000000000000000111100000, + 0b00000000000000000000000111100000, + 0b00000000000000000000001111000000, + 0b00000000000000000000011111000000, + 0b00000000000000000111111110000000, + 0b00000000000000000111111100000000, + 0b00000000000000000111111000000000, + 0b00000000000000000011100000000000, + 0b00000000000000000011100000000000, + 0b00000000000000000011100000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_RIGHT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000011111111111100000, + 0b00000000000000011111111111100000, + 0b00000000000000011111111111100000, + 0b00000000000000000000111111100000, + 0b00000000000000000000111111100000, + 0b00000000000000000001111111100000, + 0b00000000000000000011111111100000, + 0b00000000011111110111110111100000, + 0b00000000111111111111100111100000, + 0b00000001111111111111000111100000, + 0b00000011111000111110000111100000, + 0b00000011110000001100000011000000, + 0b00000111100000000000000000000000, + 0b00000111100000000000000000000000, + 0b00000111100000000000000000000000, + 0b00000111100000000000000000000000, + 0b00000011110000000000000000000000, + 0b00000011111000000000000000000000, + 0b00000001111111100000000000000000, + 0b00000000111111100000000000000000, + 0b00000000011111100000000000000000, + 0b00000000000111000000000000000000, + 0b00000000000111000000000000000000, + 0b00000000000111000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_LEFT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000011000000000000000000000, + 0b00000000111100000000111111100000, + 0b00000001111100000011111111110000, + 0b00000011111000000111111111111000, + 0b00000111110000000111110001111100, + 0b00001111100000001111000000111100, + 0b00011111111111111111000000011110, + 0b00111111111111111110000000011110, + 0b00111111111111111110000000011110, + 0b00011111111111111110000000011110, + 0b00001111100000000000000000111100, + 0b00000111110000000000000001111100, + 0b00000011111000000000011111111000, + 0b00000001111100000000011111110000, + 0b00000000111100000000011111100000, + 0b00000000011000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000001110000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + knownImages.add(new IconType(NavigationInfoSpec.ACTION_ROUNDABOUT_RIGHT, new int[]{ + 0b00000000000000000000000000000000,// GUESSED - this may not be an exact match + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000011000000000, + 0b00000111111100000000111100000000, + 0b00001111111111000000111110000000, + 0b00011111111111100000011111000000, + 0b00111110001111100000001111100000, + 0b00111100000011110000000111110000, + 0b01111000000011111111111111111000, + 0b01111000000001111111111111111100, + 0b01111000000001111111111111111100, + 0b01111000000001111111111111111000, + 0b00111100000000000000000111110000, + 0b00111110000000000000001111100000, + 0b00011111111000000000011111000000, + 0b00001111111000000000111110000000, + 0b00000111111000000000111100000000, + 0b00000001110000000000011000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000001110000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000000 + })); + } + + public boolean handle(Context context, StatusBarNotification sbn) { + if (sbn.getPackageName().equals("com.google.android.apps.maps")) { + Notification notification = sbn.getNotification(); + if (!NotificationCompat.getLocalOnly(notification)) + return false; // ignore non-local notifications + + String distance = (notification.extras.get("android.title")==null) ? "" : + notification.extras.get("android.title").toString(); // eg 100 yd + String instruction = (notification.extras.get("android.text")==null) ? "" : + notification.extras.get("android.text").toString(); // eg: High St towards Blah + String navLine = (notification.extras.get("android.subText")==null) ? "" : + notification.extras.get("android.subText").toString().replaceAll("\u00A0", " "); // eg: 13 min · 4.6 mi · 11:55 ETA + String[] navLines = navLine.split("·"); + for (int i = 0; i < navLines.length; i++) navLines[i] = navLines[i].trim(); + if (navLines.length < 3) return false; // not in the format we expected - might be 'Shared with you' notification + // navLines now has at least 3 elements + LOG.info("Navigation: " + instruction + "," + distance + "," + navLines[0] + "," + navLines[1] + "," + navLines[2]); + int matchedIcon = -1; + // getLargeIcon only works in API 23+ - don't try and get icons on older devices + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + Icon icon = notification.getLargeIcon(); + if (icon != null) { + // We convert the icon to a bitmap, then to x 32x32 1bpp which we'll check against known images + Drawable drawable = icon.loadDrawable(context); + Bitmap bitmap = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + int[] pixelsRGBA = new int[32 * 32]; + bitmap.getPixels(pixelsRGBA, 0, 32, 0, 0, 32, 32); + int[] pixelPack = new int[32]; // pixels packed down 1bpp + char[] pixelStringChars = new char[33 * 32]; + + for (int y = 0; y < 32; y++) { + int pack = 0; + for (int x = 0; x < 32; x++) { + int pixel = ((pixelsRGBA[(y * 32) + x] & 0x80000000) != 0) ? 1 : 0; + pack = (pack << 1) | pixel; // check top bit (=alpha) + pixelStringChars[x + y * 33] = (pixel != 0) ? '1' : '0'; + } + pixelStringChars[32 + y * 33] = '\n'; + pixelPack[y] = pack; + } + // This is now a printable string showing the image, which we can log if we don't recognise it + String pixelString = new String(pixelStringChars); + + int bestDiff = 100; + for (int i = 0; i < knownImages.size(); i++) { + IconType knownImage = knownImages.get(i); + int diff = 0; + // Work out how many bits differ over the whole image + for (int j = 0; j < 32; j++) + diff += Integer.bitCount(knownImage.icon[j] ^ pixelPack[j]); + // if it's close enough, match + if (diff < 32 && diff < bestDiff) { + matchedIcon = knownImage.iconType; + bestDiff = diff; + } + } + if (matchedIcon < 0) { + LOG.info("Icon NEW:\n" + pixelString); + knownImages.add(new IconType(255, pixelPack)); + } + } + } + NavigationInfoSpec navInfo = new NavigationInfoSpec(); + if (matchedIcon>=0) + navInfo.nextAction = matchedIcon; + navInfo.instruction = instruction; + if (distance != null) { + float distanceMultiplier = 1; + String distanceUnit = distance.replaceAll("[\\d.\\s]", "").toLowerCase(); + if (distanceUnit.equals("m")) distanceMultiplier = 1; + else if (distanceUnit.equals("mi")) distanceMultiplier = 1609.34f; + else if (distanceUnit.equals("yd")) distanceMultiplier = 0.9144f; + else if (distanceUnit.equals("ft")) distanceMultiplier = 0.3048f; + else if (distanceUnit.equals("km")) distanceMultiplier = 1000; + else LOG.info("Unknown distance unit '"+distanceUnit+"'"); + try { + navInfo.distanceToTurn = Math.round(distanceMultiplier * Float.parseFloat(distance.replaceAll("[^\\d.]", ""))); + } catch (NumberFormatException e) { + LOG.info("Couldn't parse distance"); + } + } + if (navLines[2].contains("ETA")) + navInfo.ETA = navLines[2].replace("ETA","").trim(); + GBApplication.deviceService().onSetNavigationInfo(navInfo); + + return true; + } + return false; + } + + public boolean handleRemove(StatusBarNotification sbn) { + if (sbn.getPackageName().equals("com.google.android.apps.maps")) { + Notification notification = sbn.getNotification(); + if (!NotificationCompat.getLocalOnly(notification)) + return false; // ignore non-local notifications + NavigationInfoSpec navInfo = new NavigationInfoSpec(); // send a blank one to remove + GBApplication.deviceService().onSetNavigationInfo(navInfo); + return true; + } + return false; + } +} 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 6ce844638..1e69b1736 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -294,7 +294,8 @@ public class GBDeviceService implements DeviceService { Intent intent = createIntent().setAction(ACTION_SETNAVIGATIONINFO) .putExtra(EXTRA_NAVIGATION_INSTRUCTION, navigationInfoSpec.instruction) .putExtra(EXTRA_NAVIGATION_NEXT_ACTION, navigationInfoSpec.nextAction) - .putExtra(EXTRA_NAVIGATION_DISTANCE_TO_TURN, navigationInfoSpec.distanceToTurn); + .putExtra(EXTRA_NAVIGATION_DISTANCE_TO_TURN, navigationInfoSpec.distanceToTurn) + .putExtra(EXTRA_NAVIGATION_ETA, navigationInfoSpec.ETA); invokeService(intent); } 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 da182f47f..02a530ced 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java @@ -114,6 +114,7 @@ public interface DeviceService extends EventHandler { String EXTRA_NAVIGATION_INSTRUCTION = "navigation_instruction"; String EXTRA_NAVIGATION_DISTANCE_TO_TURN = "navigation_distance_to_turn"; String EXTRA_NAVIGATION_NEXT_ACTION = "navigation_next_action"; + String EXTRA_NAVIGATION_ETA = "navigation_eta"; String EXTRA_APP_UUID = "app_uuid"; String EXTRA_APP_START = "app_start"; String EXTRA_APP_CONFIG = "app_config"; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NavigationInfoSpec.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NavigationInfoSpec.java index 517a62d8e..b35f02dd1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NavigationInfoSpec.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/NavigationInfoSpec.java @@ -31,8 +31,12 @@ public class NavigationInfoSpec { public static final int ACTION_OFFROUTE = 12; public static final int ACTION_ROUNDABOUT_RIGHT = 13; public static final int ACTION_ROUNDABOUT_LEFT = 14; + public static final int ACTION_ROUNDABOUT_STRAIGHT = 15; + public static final int ACTION_FINISH = 16; + // ETA? Total Distance? public String instruction; - public int distanceToTurn; - public int nextAction; + public int distanceToTurn; ///< Distance to turn (in metres?) + public int nextAction; ///< One of the ACTION_ constants + public String ETA; ///< Estimated time of Arrival } 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 298666deb..29a5026c8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -186,6 +186,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_MUS import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_DISTANCE_TO_TURN; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_INSTRUCTION; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_NEXT_ACTION; +import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NAVIGATION_ETA; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_ACTIONS; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_BODY; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_DNDSUPPRESSED; @@ -890,6 +891,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere navigationInfoSpec.instruction = intent.getStringExtra(EXTRA_NAVIGATION_INSTRUCTION); navigationInfoSpec.nextAction = intent.getIntExtra(EXTRA_NAVIGATION_NEXT_ACTION,0); navigationInfoSpec.distanceToTurn = intent.getIntExtra(EXTRA_NAVIGATION_DISTANCE_TO_TURN,0); + navigationInfoSpec.ETA = intent.getStringExtra(EXTRA_NAVIGATION_ETA); deviceSupport.onSetNavigationInfo(navigationInfoSpec); break; case ACTION_REQUEST_APPINFO: diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java index ebfaf351a..f04af56d5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java @@ -116,6 +116,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; +import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; @@ -1526,4 +1527,26 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { } } + @Override + public void onSetNavigationInfo(NavigationInfoSpec navigationInfoSpec) { + try { + JSONObject o = new JSONObject(); + o.put("t", "nav"); + if (navigationInfoSpec.instruction!=null) + o.put("instr", navigationInfoSpec.instruction); + o.put("distance", navigationInfoSpec.distanceToTurn); + String[] navActions = { + "","continue", "left", "left_sharp", "left_slight", "right", "right_slight", + "right_sharp", "keep_left", "keep_right", "uturn_left", "uturn_right", + "offroute", "roundabout_right", "roundabout_left", "roundabout_straight", "finish"}; + if (navigationInfoSpec.nextAction>0 && navigationInfoSpec.nextAction