mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Garmin: Send app notification icons
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@ public class HttpHandler {
|
||||
agpsHandler = new AgpsHandler(deviceSupport);
|
||||
contactsHandler = new ContactsHandler(deviceSupport);
|
||||
oauthHandler = new OauthHandler(deviceSupport);
|
||||
imageServiceHandler = new ImageServiceHandler();
|
||||
imageServiceHandler = new ImageServiceHandler(deviceSupport);
|
||||
}
|
||||
|
||||
public GdiHttpService.HttpService handle(final GdiHttpService.HttpService httpService) {
|
||||
|
||||
+120
@@ -1,17 +1,29 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.http;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiHttpService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils;
|
||||
|
||||
public class ImageServiceHandler {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ImageServiceHandler.class);
|
||||
@@ -20,6 +32,12 @@ public class ImageServiceHandler {
|
||||
//.serializeNulls()
|
||||
.create();
|
||||
|
||||
private final GarminSupport deviceSupport;
|
||||
|
||||
public ImageServiceHandler(final GarminSupport deviceSupport) {
|
||||
this.deviceSupport = deviceSupport;
|
||||
}
|
||||
|
||||
public GarminHttpResponse handleRequest(final GarminHttpRequest request) {
|
||||
if (request.getRawRequest().getMethod() != GdiHttpService.HttpService.Method.GET) {
|
||||
LOG.warn("Known image service requests should be GET");
|
||||
@@ -33,6 +51,46 @@ public class ImageServiceHandler {
|
||||
|
||||
final String ownerAliasId = request.getQuery().get("ownerAliasId");
|
||||
|
||||
final Drawable icon = NotificationUtils.getAppIcon(
|
||||
deviceSupport.getContext(),
|
||||
ownerAliasId
|
||||
);
|
||||
|
||||
if (icon == null) {
|
||||
LOG.warn("Failed to get icon for {}", ownerAliasId);
|
||||
|
||||
return createNotFoundResponse(ownerAliasId);
|
||||
}
|
||||
|
||||
final String imageSizeStr = request.getQuery().get("imageSize");
|
||||
if (imageSizeStr == null) {
|
||||
LOG.warn("No image size query param");
|
||||
return createNotFoundResponse(ownerAliasId);
|
||||
}
|
||||
|
||||
final int imageSize = Integer.parseInt(imageSizeStr);
|
||||
final byte[] encodedPng = encodeToPng(icon, imageSize);
|
||||
final byte[] header = createImageHeader(encodedPng.length, imageSize);
|
||||
|
||||
final ByteBuffer buf = ByteBuffer.allocate(header.length + encodedPng.length);
|
||||
buf.put(header);
|
||||
buf.put(encodedPng);
|
||||
|
||||
final GarminHttpResponse response = new GarminHttpResponse();
|
||||
|
||||
response.setStatus(200);
|
||||
response.getHeaders().put("Content-Type", "image/png");
|
||||
response.getHeaders().put("imagetype", "ICON");
|
||||
response.getHeaders().put("original-image-size", String.valueOf(encodedPng.length));
|
||||
response.getHeaders().put("ownerid", ownerAliasId);
|
||||
response.getHeaders().put("ownertype", "APP");
|
||||
response.setBody(buf.array());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static GarminHttpResponse createNotFoundResponse(final String ownerAliasId) {
|
||||
final String requestId = UUID.randomUUID().toString();
|
||||
|
||||
final ErrorResponse errorResponse = new ErrorResponse(requestId, Collections.singletonList(new Error(
|
||||
@@ -41,6 +99,7 @@ public class ImageServiceHandler {
|
||||
)));
|
||||
|
||||
final GarminHttpResponse response = new GarminHttpResponse();
|
||||
|
||||
response.setStatus(404);
|
||||
response.setBody(GSON.toJson(errorResponse).getBytes(StandardCharsets.UTF_8));
|
||||
response.getHeaders().put("Content-Type", "application/json");
|
||||
@@ -49,6 +108,67 @@ public class ImageServiceHandler {
|
||||
return response;
|
||||
}
|
||||
|
||||
private static byte[] encodeToPng(final Drawable icon, final int imageSize) {
|
||||
final Bitmap bitmap = Bitmap.createBitmap(imageSize, imageSize, Bitmap.Config.ARGB_8888);
|
||||
final Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
icon.setBounds(0, 0, imageSize, imageSize);
|
||||
icon.draw(canvas);
|
||||
|
||||
final ByteArrayOutputStream pngBaos = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, pngBaos);
|
||||
|
||||
return pngBaos.toByteArray();
|
||||
}
|
||||
|
||||
private static byte[] createImageHeader(final int pngLength, final int imageSize) {
|
||||
final ByteBuffer buf = ByteBuffer.allocate(43).order(ByteOrder.BIG_ENDIAN);
|
||||
|
||||
// 0c 11 ee 5e
|
||||
buf.putInt(0x0c);
|
||||
buf.putInt(0x11);
|
||||
buf.putInt(0xee);
|
||||
buf.putInt(0x5e);
|
||||
|
||||
buf.putInt(pngLength + 0x23);
|
||||
buf.putShort((short) imageSize);
|
||||
buf.putShort((short) imageSize);
|
||||
|
||||
// ff ff 00 40 00 00 10 00 00 1c 00 00 1c 10
|
||||
buf.put((byte) 0xff);
|
||||
buf.put((byte) 0xff);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x40);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x10);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x1c);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x1c);
|
||||
buf.put((byte) 0x10);
|
||||
|
||||
buf.putShort((short) imageSize);
|
||||
buf.putShort((short) imageSize);
|
||||
|
||||
// 00 02 04 00 00 00 00 04 00
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x02);
|
||||
buf.put((byte) 0x04);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x00);
|
||||
buf.put((byte) 0x04);
|
||||
buf.put((byte) 0x00);
|
||||
|
||||
buf.put(BLETypeConversions.fromUint32(pngLength));
|
||||
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
public record ErrorResponse(String requestId, List<Error> errors) {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user