mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-04 17:27:24 +01:00
Add support for picture attachments in notifications
Also adds a local cache for pictures which is handled by the NotificationListener itself. If the picture is hosted in a third party content provider it gets queried. If the Bitmap is embedded in the notification, the local cache is used. In any case the NotificationSpec just holds a String to the absolute file path
This commit is contained in:
parent
db33bc3ee9
commit
1435c3a937
@ -26,10 +26,12 @@ import android.app.ActivityManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@ -40,6 +42,7 @@ import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.MediaStore;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
@ -53,6 +56,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -120,6 +127,17 @@ public class NotificationListener extends NotificationListenerService {
|
||||
add("mikado.bizcalpro");
|
||||
}};
|
||||
|
||||
private static final Set<String> supportedPictureMimeTypes = new HashSet<String>() {{
|
||||
add("image/"); //for im.vector.app
|
||||
add("image/jpeg");
|
||||
add("image/png");
|
||||
add("image/gif");
|
||||
add("image/bmp");
|
||||
add("image/webp");
|
||||
}};
|
||||
|
||||
private File notificationPictureCacheDirectory;
|
||||
|
||||
public static ArrayList<String> notificationStack = new ArrayList<>();
|
||||
private static ArrayList<Integer> notificationsActive = new ArrayList<Integer>();
|
||||
|
||||
@ -240,6 +258,8 @@ public class NotificationListener extends NotificationListenerService {
|
||||
filterLocal.addAction(ACTION_MUTE);
|
||||
filterLocal.addAction(ACTION_REPLY);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
|
||||
createNotificationPictureCacheDirectory();
|
||||
cleanUpNotificationPictureProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -247,6 +267,7 @@ public class NotificationListener extends NotificationListenerService {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
|
||||
notificationStack.clear();
|
||||
notificationsActive.clear();
|
||||
cleanUpNotificationPictureProvider();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@ -648,6 +669,41 @@ public class NotificationListener extends NotificationListenerService {
|
||||
notificationSpec.body = sanitizeUnicode(contentCS.toString());
|
||||
}
|
||||
|
||||
NotificationCompat.MessagingStyle messagingStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(notification);
|
||||
if (messagingStyle != null) {
|
||||
List<NotificationCompat.MessagingStyle.Message> messages = messagingStyle.getMessages();
|
||||
if (!messages.isEmpty()) {
|
||||
// Get the last message (assumed to be the most recent)
|
||||
NotificationCompat.MessagingStyle.Message lastMessage = messages.get(messages.size() - 1);
|
||||
|
||||
if (supportedPictureMimeTypes.contains(lastMessage.getDataMimeType())) {
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
try (Cursor cursor = contentResolver.query(lastMessage.getDataUri(), null, null, null, null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
||||
notificationSpec.picturePath = cursor.getString(dataIndex);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extras.containsKey(NotificationCompat.EXTRA_PICTURE)) {
|
||||
final Bitmap bmp = (Bitmap) extras.get(NotificationCompat.EXTRA_PICTURE);
|
||||
File pictureFile = new File(this.notificationPictureCacheDirectory, String.valueOf(notificationSpec.getId()));
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(pictureFile)) {
|
||||
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
|
||||
notificationSpec.picturePath = pictureFile.getAbsolutePath();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to save picture to notification cache: {}", e.getMessage());
|
||||
} finally {
|
||||
bmp.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
if (notificationSpec.type == NotificationType.COL_REMINDER
|
||||
&& notificationSpec.body == null
|
||||
&& notificationSpec.title != null) {
|
||||
@ -775,6 +831,7 @@ public class NotificationListener extends NotificationListenerService {
|
||||
for (int notificationId : notificationsActive) {
|
||||
if (!activeNotificationsIds.contains(notificationId)) {
|
||||
notificationsToRemove.add(notificationId);
|
||||
deleteNotificationPicture(notificationId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,6 +855,27 @@ public class NotificationListener extends NotificationListenerService {
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteNotificationPicture(int notificationId) {
|
||||
File pictureFile = new File(this.notificationPictureCacheDirectory, String.valueOf(notificationId));
|
||||
if (pictureFile.exists())
|
||||
pictureFile.delete();
|
||||
}
|
||||
|
||||
private void cleanUpNotificationPictureProvider() {
|
||||
File[] pictureFiles = this.notificationPictureCacheDirectory.listFiles();
|
||||
if (pictureFiles == null)
|
||||
return;
|
||||
|
||||
for (File pictureFile : pictureFiles) {
|
||||
pictureFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void createNotificationPictureCacheDirectory() {
|
||||
final File cacheDir = getApplicationContext().getExternalCacheDir();
|
||||
this.notificationPictureCacheDirectory = new File(cacheDir, "notification-pictures");
|
||||
this.notificationPictureCacheDirectory.mkdir();
|
||||
}
|
||||
private void logNotification(StatusBarNotification sbn, boolean posted) {
|
||||
LOG.debug(
|
||||
"Notification {} {}: packageName={}, priority={}, category={}",
|
||||
|
@ -179,6 +179,7 @@ public class GBDeviceService implements DeviceService {
|
||||
.putExtra(EXTRA_NOTIFICATION_PEBBLE_COLOR, notificationSpec.pebbleColor)
|
||||
.putExtra(EXTRA_NOTIFICATION_SOURCEAPPID, notificationSpec.sourceAppId)
|
||||
.putExtra(EXTRA_NOTIFICATION_ICONID, notificationSpec.iconId)
|
||||
.putExtra(NOTIFICATION_PICTURE_PATH, notificationSpec.picturePath)
|
||||
.putExtra(EXTRA_NOTIFICATION_DNDSUPPRESSED, notificationSpec.dndSuppressed);
|
||||
invokeService(intent);
|
||||
}
|
||||
|
@ -97,6 +97,7 @@ public interface DeviceService extends EventHandler {
|
||||
String EXTRA_NOTIFICATION_ACTIONS = "notification_actions";
|
||||
String EXTRA_NOTIFICATION_PEBBLE_COLOR = "notification_pebble_color";
|
||||
String EXTRA_NOTIFICATION_ICONID = "notification_iconid";
|
||||
String NOTIFICATION_PICTURE_PATH = "notification_picture_path";
|
||||
String EXTRA_NOTIFICATION_DNDSUPPRESSED = "notification_dndsuppressed";
|
||||
String EXTRA_FIND_START = "find_start";
|
||||
String EXTRA_VIBRATION_INTENSITY = "vibration_intensity";
|
||||
|
@ -48,6 +48,7 @@ public class NotificationSpec {
|
||||
*/
|
||||
public int iconId;
|
||||
|
||||
public String picturePath;
|
||||
/**
|
||||
* The color that should be assigned to this notification when displayed on a Pebble
|
||||
*/
|
||||
|
@ -827,6 +827,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
notificationSpec.flags = intent.getIntExtra(EXTRA_NOTIFICATION_FLAGS, 0);
|
||||
notificationSpec.sourceAppId = intent.getStringExtra(EXTRA_NOTIFICATION_SOURCEAPPID);
|
||||
notificationSpec.iconId = intent.getIntExtra(EXTRA_NOTIFICATION_ICONID, 0);
|
||||
notificationSpec.picturePath = intent.getStringExtra(NOTIFICATION_PICTURE_PATH);
|
||||
notificationSpec.dndSuppressed = intent.getIntExtra(EXTRA_NOTIFICATION_DNDSUPPRESSED, 0);
|
||||
|
||||
if (notificationSpec.type == NotificationType.GENERIC_SMS && notificationSpec.phoneNumber != null) {
|
||||
|
Loading…
Reference in New Issue
Block a user