From 73dac680e564c2a55cda544e9996da9f829dd4ac Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 1 Sep 2020 14:04:38 +0200 Subject: [PATCH] show notification if message failed to deliver. closes #3540 --- .travis.yml | 2 +- .../conversations/entities/Conversation.java | 12 +++++ .../services/NotificationService.java | 45 +++++++++++++++++- .../services/XmppConnectionService.java | 5 +- .../res/drawable-hdpi/ic_error_white_24dp.png | Bin 0 -> 324 bytes .../res/drawable-mdpi/ic_error_white_24dp.png | Bin 0 -> 232 bytes .../drawable-xhdpi/ic_error_white_24dp.png | Bin 0 -> 431 bytes .../drawable-xxhdpi/ic_error_white_24dp.png | Bin 0 -> 614 bytes .../drawable-xxxhdpi/ic_error_white_24dp.png | Bin 0 -> 814 bytes src/main/res/values/strings.xml | 6 +++ 10 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 src/main/res/drawable-hdpi/ic_error_white_24dp.png create mode 100644 src/main/res/drawable-mdpi/ic_error_white_24dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_error_white_24dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_error_white_24dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_error_white_24dp.png diff --git a/.travis.yml b/.travis.yml index 4af69e484..239637ba4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ android: - '.+' before_script: - mkdir libs - - wget -O libs/libwebrtc-m85.aar http://gultsch.de/files/libwebrtc-m85.aar + - wget -O libs/libwebrtc-m85.aar https://gultsch.de/files/libwebrtc-m85.aar script: - ./gradlew assembleConversationsFreeSystemRelease - ./gradlew assembleQuicksyFreeCompatRelease diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 1a28ba20e..cdd891966 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -186,6 +186,18 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl return null; } + public int countFailedDeliveries() { + int count = 0; + synchronized (this.messages) { + for(final Message message : this.messages) { + if (message.getStatus() == Message.STATUS_SEND_FAILED) { + ++count; + } + } + } + return count; + } + public Message getLastEditableMessage() { synchronized (this.messages) { for (final Message message : Lists.reverse(this.messages)) { diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index a77b923f2..500f95a54 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -83,6 +83,7 @@ public class NotificationService { private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6; private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8; public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; + private static final int DELIVERY_FAILED_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 12; private final XmppConnectionService mXmppConnectionService; private final LinkedHashMap> notifications = new LinkedHashMap<>(); private final HashMap mBacklogMessageCounter = new HashMap<>(); @@ -221,9 +222,20 @@ public class NotificationService { quietHoursChannel.setSound(null, null); notificationManager.createNotificationChannel(quietHoursChannel); + + final NotificationChannel deliveryFailedChannel = new NotificationChannel("delivery_failed", + c.getString(R.string.delivery_failed_channel_name), + NotificationManager.IMPORTANCE_DEFAULT); + deliveryFailedChannel.setShowBadge(false); + deliveryFailedChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) + .build()); + deliveryFailedChannel.setGroup("chats"); + notificationManager.createNotificationChannel(deliveryFailedChannel); } - public boolean notify(final Message message) { + private boolean notify(final Message message) { final Conversation conversation = (Conversation) message.getConversation(); return message.getStatus() == Message.STATUS_RECEIVED && !conversation.isMuted() @@ -343,6 +355,37 @@ public class NotificationService { } } + public void pushFailedDelivery(final Message message) { + final Conversation conversation = (Conversation) message.getConversation(); + final boolean isScreenOn = mXmppConnectionService.isInteractive(); + if (this.mIsInForeground && isScreenOn && this.mOpenConversation == message.getConversation()) { + Log.d(Config.LOGTAG, message.getConversation().getAccount().getJid().asBareJid() + ": suppressing failed delivery notification because conversation is open"); + return; + } + final PendingIntent pendingIntent = createContentIntent(conversation); + final int notificationId = generateRequestCode(conversation, 0) + DELIVERY_FAILED_NOTIFICATION_ID; + final int failedDeliveries = conversation.countFailedDeliveries(); + final Notification notification = + new Builder(mXmppConnectionService, "delivery_failed") + .setContentTitle(conversation.getName()) + .setAutoCancel(true) + .setSmallIcon(R.drawable.ic_error_white_24dp) + .setContentText(mXmppConnectionService.getResources().getQuantityText(R.plurals.some_messages_could_not_be_delivered, failedDeliveries)) + .setGroup("delivery_failed") + .setContentIntent(pendingIntent).build(); + final Notification summaryNotification = + new Builder(mXmppConnectionService, "delivery_failed") + .setContentTitle(mXmppConnectionService.getString(R.string.failed_deliveries)) + .setContentText(mXmppConnectionService.getResources().getQuantityText(R.plurals.some_messages_could_not_be_delivered, 1024)) + .setSmallIcon(R.drawable.ic_error_white_24dp) + .setGroup("delivery_failed") + .setGroupSummary(true) + .setAutoCancel(true) + .build(); + notify(notificationId, notification); + notify(DELIVERY_FAILED_NOTIFICATION_ID, summaryNotification); + } + public void showIncomingCallNotification(final AbstractJingleConnection.Id id, final Set media) { final Intent fullScreenIntent = new Intent(mXmppConnectionService, RtpSessionActivity.class); fullScreenIntent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().asBareJid().toEscapedString()); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index d539ff30f..3225be67d 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -3922,7 +3922,7 @@ public class XmppConnectionService extends Service { } - public void markMessage(Message message, int status, String errorMessage) { + public void markMessage(final Message message, final int status, final String errorMessage) { final int oldStatus = message.getStatus(); if (status == Message.STATUS_SEND_FAILED && (oldStatus == Message.STATUS_SEND_RECEIVED || oldStatus == Message.STATUS_SEND_DISPLAYED)) { return; @@ -3934,6 +3934,9 @@ public class XmppConnectionService extends Service { message.setStatus(status); databaseBackend.updateMessage(message, false); updateConversationUi(); + if (oldStatus != status && status == Message.STATUS_SEND_FAILED) { + mNotificationService.pushFailedDelivery(message); + } } private SharedPreferences getPreferences() { diff --git a/src/main/res/drawable-hdpi/ic_error_white_24dp.png b/src/main/res/drawable-hdpi/ic_error_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..69cbb1e0bd3807d27f4197a9328467df8397e169 GIT binary patch literal 324 zcmV-K0lWT*P)gGbr{!4DC&5DTe055otv=(oBcbwiQ9yc={9S=wqGvvb{)YG_-cTkwp}f z`yT&OF!RTU{~tMq?Z(U8YgIoe@jCRcP1rd4N|RY{%7e{VkWP)9pDS`rt8>j14g%vJK^s@CixA{JOk4QTA=JOC;K#wgGmprXKRz!nAc zA3zb4$$%jWbOzK>BbED)TQ7myeVhoz2|$d zb8`?1e$Og=AO=p3^FQ2v1vo`5um^p+ctP+U`du{Cg2BIYu^K^T*z8PSr06@ zpYw0-H`M_jNko7vwcEfLL;x7x0$h$_z@D56d;>86zNo-J6zHkIN)+%_AQS}x6*!9m zkqRWDK>P&Y>5nKxvcT|~X3kfEK9Y4+powG+6>vF-{mDCWD&Q~@1Kw`$gF3O$!g;S- znKKb!qTk6CPGs#5B|YHKA!{wuhu4fO{lqZ=9vf_1lQ#nnMN49>{rFYJqtG0D3I)9=d59Kjp*^Xg722Dkhl0YY!4OL5BZS<; z61=$^@!wOAvpYLG^KB0M-}Ax`HcMva+o_^St*D4Hn>1TvB%jTH^te+N{_IE%A#iov~;Ww9O+~8_}=>n&BI^ zI--;nG>?zXu6dmW zsy^r^5`EVNtszxi5A;CV{@^j=ui!6F8|2Y@HE50q*%Fo?Q`{q+AHQPUL%N-$MgCaywU1ax z+6G;Ug3gooWpz=|Tb-?RTMXpu?d?~P>4jz8YL)m<^&~w09$TEDXaAWylm9vhgN*rOUk4)Pc;58VL zwSX;~BhD&6FzauW`W`-6GCecK;!P$1b;o#Px*Fj`{^R2dS@F z);Z*a4t<7%gbeA^;g|#7@k-=V3xlfw6`%t24_R#olFFzoX8-^I07*qoM6N<$f=(S9 A<^TWy literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-xxxhdpi/ic_error_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_error_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..830fb7e1e6860117fa31155fa24e5002984d1444 GIT binary patch literal 814 zcmV+}1JV46P)OpZvS)hbY2bjDdCIt{;m^E&&TAfu=g!~1xk)e#84w<3VA3%)v zT;W8QWNGmlFhK<;J7(NFz$5aw(K=mT04Ay7R#jfR3y83c+nI#j0wmeRi*`u30qCQQ zR~6}T8t{Y@ysSdMlYl->@VW}UP63jX@uMOMCjb$4@v9xe_5sWInQ0d=iQi4w0rXJA z@2Ye)4#*>+^+o{`NNKDQK#U4@`v3FnbVSrT;2nqoz?@Y;8&{$L7sRarG9U^7(^dc> z%HjYeLi&JV5C?!keZZPXz=|#)&W%Vwji?@A6hs1GL=Rw!1?2PqMX`W=9Y80D1wcX# zNQ(xf)PSsLz?>SeBpP6<0o$Shc{QLQ8nCAZoQnpWssXp60d+OtUNqqDF967Yh5q!9 z__zNV-9mDkYQQ3rn^yy}NN!dQNF%u+H6V%P+SLGq1Ef~K&;iUNwGVoL=Sc0T9w0_t zOngoing calls Silent messages This notification group is used to display notifications that should not trigger any sound. For example when being active on another device (Grace Period). + Failed deliveries Message notification settings Incoming calls notification settings Importance, Sound, Vibrate @@ -942,4 +943,9 @@ View %1$d Participant View %1$d Participants + + A message could not be delivered + Some messages could not be delivered + + Failed deliveries