From e665ca2b0dbca828421ec5c6225ab0baaf1fba33 Mon Sep 17 00:00:00 2001 From: Arne Date: Tue, 5 Jul 2022 23:21:38 +0200 Subject: [PATCH] aut resend failed message --- .../conversations/entities/Conversation.java | 13 +++++++ .../siacs/conversations/entities/Message.java | 8 ++++ .../services/XmppConnectionService.java | 38 ++++++++++++++++++- .../conversations/ui/SettingsActivity.java | 2 + .../ui/adapter/MessageAdapter.java | 2 +- src/main/res/values/defaults.xml | 2 + src/main/res/values/strings.xml | 4 ++ src/main/res/xml/preferences.xml | 14 +++++++ 8 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 20e40e418..5cb9ca697 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -263,6 +263,19 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl onMessageFound.onMessageFound(result); } } + public void findResendAbleFailedMessage(OnMessageFound onMessageFound) { + final ArrayList results = new ArrayList<>(); + synchronized (this.messages) { + for (final Message message : this.messages) { + if (message.getStatus() == Message.STATUS_SEND_FAILED && !message.isFileOrImage()) { + results.add(message); + } + } + } + for (final Message result : results) { + onMessageFound.onMessageFound(result); + } + } public void findUnreadMessagesAndCalls(OnMessageFound onMessageFound) { final ArrayList results = new ArrayList<>(); diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 148b0e011..9446200ab 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -124,6 +124,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable private String errorMessage = null; private Set readByMarkers = new CopyOnWriteArraySet<>(); private String retractId = null; + protected int resendCount = 0; private Boolean isGeoUri = null; private Boolean isXmppUri = null; @@ -1127,4 +1128,11 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable message.setType(isFile ? Message.TYPE_PRIVATE_FILE : Message.TYPE_PRIVATE); return true; } + + public int getResendCount(){ + return resendCount; + } + public int increaseResendCount(){ + return ++resendCount; + } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 3c30f99e4..a1d86b51f 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -15,6 +15,8 @@ import static eu.siacs.conversations.ui.SettingsActivity.SHOW_OWN_ACCOUNTS; import static eu.siacs.conversations.ui.SettingsActivity.USE_INNER_STORAGE; import static eu.siacs.conversations.utils.RichPreview.RICH_LINK_METADATA; import static eu.siacs.conversations.utils.StorageHelper.getAppMediaDirectory; +import android.content.res.Resources; +import android.os.Handler; import android.Manifest; import androidx.annotation.RequiresApi; @@ -231,6 +233,7 @@ public class XmppConnectionService extends Service { private final SerialSingleThreadExecutor mNotificationExecutor = new SerialSingleThreadExecutor("NotificationExecutor"); public final SerialSingleThreadExecutor mWebPreviewExecutor = new SerialSingleThreadExecutor("WebPreview"); public final SerialSingleThreadExecutor mNotificationChannelExecutor = new SerialSingleThreadExecutor("updateNotificationChannels"); + public final SerialSingleThreadExecutor mMessageResendTaskExecuter = new SerialSingleThreadExecutor("MessageResender"); private final ReplacingTaskManager mRosterSyncTaskManager = new ReplacingTaskManager(); private final IBinder mBinder = new XmppConnectionBinder(); private final List conversations = new CopyOnWriteArrayList<>(); @@ -881,6 +884,7 @@ public class XmppConnectionService extends Service { for (Conversation conversation : conversations) { if (conversation.getAccount() == account && !account.pendingConferenceJoins.contains(conversation)) { resendFailedFileMessages(conversation); + resendFailedMessages(conversation); } } final boolean lowTimeout = isInLowPingTimeoutMode(account); @@ -911,7 +915,9 @@ public class XmppConnectionService extends Service { } } } - + public int maxResendTime(){ + return Integer.parseInt(getPreferences().getString(SettingsActivity.MAX_RESEND_TIME, getResources().getString(R.string.max_resend_time))); + } private void deleteWebpreviewCache() { new Thread(() -> { try { @@ -1993,7 +1999,18 @@ public class XmppConnectionService extends Service { mDatabaseWriterExecutor.execute((runnable)); } - + private void resendFailedMessages(final Conversation conversation) { + final Runnable runnable = () -> { + conversation.findResendAbleFailedMessage(message -> { + if (message.increaseResendCount() < maxResendTime()) { + Log.d(Config.LOGTAG, "Resend failed message " + message.getErrorMessage() + " at times " + message.getResendCount() + " bytes for " + conversation.getJid()); + // because it'll use a custom delay here, only the last time will delay the message. + resendFailedMessages(message); + } + }); + }; + mMessageResendTaskExecuter.execute((runnable)); + } private void resendFailedFileMessages(final Conversation conversation) { final Runnable runnable = () -> { conversation.findFailedMessagesWithFiles(message -> { @@ -4563,8 +4580,25 @@ public class XmppConnectionService extends Service { updateConversationUi(); if (oldStatus != status && status == Message.STATUS_SEND_FAILED) { mNotificationService.pushFailedDelivery(message); + // resend it + mMessageResendTaskExecuter.execute(() -> { + try { + if (message.increaseResendCount() <= maxResendTime() / 2) { + Thread.sleep(resendDelay()); + resendFailedMessages(message); + } + } + catch (Exception ignore){ + // if system halt, give it up + Log.w(Config.LOGTAG,"System Halt, so the message resend give up"); + } + }); + } } + private long resendDelay() { + return Long.parseLong(getPreferences().getString(SettingsActivity.RESEND_DELAY, getResources().getString(R.string.resend_delay))); + } public SharedPreferences getPreferences() { return PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index 3168ba88f..3d413bb62 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -93,6 +93,8 @@ public class SettingsActivity extends XmppActivity implements public static final String MIN_ANDROID_SDK21_SHOWN = "min_android_sdk21_shown"; public static final String INDIVIDUAL_NOTIFICATION_PREFIX = "individual_notification_set_"; public static final String PAUSE_VOICE = "pause_voice_on_move_from_ear"; + public static final String MAX_RESEND_TIME = "max_resend_time"; + public static final String RESEND_DELAY = "resend_delay"; public static final int REQUEST_CREATE_BACKUP = 0xbf8701; public static final int REQUEST_IMPORT_SETTINGS = 0xbf8702; diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 1059acb8e..844faf0bc 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -277,7 +277,7 @@ public class MessageAdapter extends ArrayAdapter { break; case Message.STATUS_SEND_FAILED: DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message); - if (isResendable && file.exists()) { + if (isResendable && file.exists() || message.getResendCount() < activity.xmppConnectionService.maxResendTime()) { info = getContext().getString(R.string.send_failed_resend); } else { final String errorMessage = message.getErrorMessage(); diff --git a/src/main/res/values/defaults.xml b/src/main/res/values/defaults.xml index 388eb19ec..efc7de566 100644 --- a/src/main/res/values/defaults.xml +++ b/src/main/res/values/defaults.xml @@ -93,6 +93,8 @@ 360 720 1080 + 4 + 500 false false false diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 793fde1e9..38ee07f6e 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -1204,4 +1204,8 @@ Download failed: Invalid file Orbot not found Temporary authentication failure + Max Time of resend failed Message + When plain message send fail, the max time to resend it. when resend count bigger than half max time, message will be delay for traffic reason. + Resend Delay (MillsSecond) + Resend Delay (MillsSecond), the time for delay resend. diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index d0bee2209..c50c09408 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -474,6 +474,20 @@ android:targetClass="com.huawei.systemmanager.optimize.process.ProtectActivity" android:targetPackage="com.huawei.systemmanager" /> + +