diff --git a/src/main/java/eu/siacs/conversations/services/AttachFileToConversationRunnable.java b/src/main/java/eu/siacs/conversations/services/AttachFileToConversationRunnable.java index 5889ba333..5df423502 100644 --- a/src/main/java/eu/siacs/conversations/services/AttachFileToConversationRunnable.java +++ b/src/main/java/eu/siacs/conversations/services/AttachFileToConversationRunnable.java @@ -90,7 +90,7 @@ public class AttachFileToConversationRunnable implements Runnable, TranscoderLis private void processAsVideo() throws FileNotFoundException { Log.d(Config.LOGTAG, "processing file as video"); - mXmppConnectionService.startForcingForegroundNotification(); + mXmppConnectionService.startOngoingVideoTranscodingForegroundNotification(); mXmppConnectionService.getFileBackend().setupRelativeFilePath(message, String.format("%s.%s", message.getUuid(), "mp4")); final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message); if (Objects.requireNonNull(file.getParentFile()).mkdirs()) { @@ -109,7 +109,7 @@ public class AttachFileToConversationRunnable implements Runnable, TranscoderLis .transcode(); } catch (final RuntimeException e) { // transcode can already throw if there is an invalid file format or a platform bug - mXmppConnectionService.stopForcingForegroundNotification(); + mXmppConnectionService.stopOngoingVideoTranscodingForegroundNotification(); processAsFile(); return; } @@ -119,7 +119,7 @@ public class AttachFileToConversationRunnable implements Runnable, TranscoderLis throw new AssertionError(e); } catch (final ExecutionException e) { if (e.getCause() instanceof Error) { - mXmppConnectionService.stopForcingForegroundNotification(); + mXmppConnectionService.stopOngoingVideoTranscodingForegroundNotification(); processAsFile(); } else { Log.d(Config.LOGTAG, "ignoring execution exception. Should get handled by onTranscodeFiled() instead", e); @@ -138,7 +138,7 @@ public class AttachFileToConversationRunnable implements Runnable, TranscoderLis @Override public void onTranscodeCompleted(int successCode) { - mXmppConnectionService.stopForcingForegroundNotification(); + mXmppConnectionService.stopOngoingVideoTranscodingForegroundNotification(); final File file = mXmppConnectionService.getFileBackend().getFile(message); long convertedFileSize = mXmppConnectionService.getFileBackend().getFile(message).getSize(); Log.d(Config.LOGTAG, "originalFileSize=" + originalFileSize + " convertedFileSize=" + convertedFileSize); @@ -162,13 +162,13 @@ public class AttachFileToConversationRunnable implements Runnable, TranscoderLis @Override public void onTranscodeCanceled() { - mXmppConnectionService.stopForcingForegroundNotification(); + mXmppConnectionService.stopOngoingVideoTranscodingForegroundNotification(); processAsFile(); } @Override public void onTranscodeFailed(@NonNull @NotNull Throwable exception) { - mXmppConnectionService.stopForcingForegroundNotification(); + mXmppConnectionService.stopOngoingVideoTranscodingForegroundNotification(); Log.d(Config.LOGTAG, "video transcoding failed", exception); processAsFile(); } diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index 041f8185f..e054fe54a 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -30,6 +30,7 @@ import android.text.style.StyleSpan; import android.util.DisplayMetrics; import android.util.Log; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationCompat; @@ -108,6 +109,7 @@ public class NotificationService { public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; public static final int MISSED_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 12; private static final int DELIVERY_FAILED_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 13; + public static final int ONGOING_VIDEO_TRANSCODING_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 14; private final XmppConnectionService mXmppConnectionService; private final LinkedHashMap> notifications = new LinkedHashMap<>(); private final HashMap mBacklogMessageCounter = new HashMap<>(); @@ -1919,18 +1921,33 @@ public class NotificationService { notify(ERROR_NOTIFICATION_ID, mBuilder.build()); } - void updateFileAddingNotification(int current, Message message) { - Notification.Builder mBuilder = new Notification.Builder(mXmppConnectionService); - mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.transcoding_video)); - mBuilder.setProgress(100, current, false); - mBuilder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp); - mBuilder.setContentIntent(createContentIntent(message.getConversation())); - mBuilder.setOngoing(true); - if (Compatibility.runsTwentySix()) { - mBuilder.setChannelId("compression"); + void updateFileAddingNotification(final int current, final Message message) { + + final Notification notification = videoTranscoding(current, message); + notify(ONGOING_VIDEO_TRANSCODING_NOTIFICATION_ID, notification); + } + + private Notification videoTranscoding(final int current, @Nullable final Message message) { + final Notification.Builder builder = new Notification.Builder(mXmppConnectionService); + builder.setContentTitle(mXmppConnectionService.getString(R.string.transcoding_video)); + if (current >= 0) { + builder.setProgress(100, current, false); + } else { + builder.setProgress(100, 0, true); } - Notification notification = mBuilder.build(); - notify(FOREGROUND_NOTIFICATION_ID, notification); + builder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp); + if (message != null) { + builder.setContentIntent(createContentIntent(message.getConversation())); + } + builder.setOngoing(true); + if (Compatibility.runsTwentySix()) { + builder.setChannelId("compression"); + } + return builder.build(); + } + + public Notification getIndeterminateVideoTranscoding() { + return videoTranscoding(-1, null); } private void notify(final String tag, final int id, final Notification notification) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index a581926b8..4bc85a016 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -243,7 +243,7 @@ public class XmppConnectionService extends Service { private final ChannelDiscoveryService mChannelDiscoveryService = new ChannelDiscoveryService(this); private final ShortcutService mShortcutService = new ShortcutService(this); private final AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false); - private final AtomicBoolean mForceForegroundService = new AtomicBoolean(false); + private final AtomicBoolean mOngoingVideoTranscoding = new AtomicBoolean(false); private final AtomicBoolean mForceDuringOnCreate = new AtomicBoolean(false); private final AtomicReference ongoingCall = new AtomicReference<>(); private final OnMessagePacketReceived mMessageParser = new MessageParser(this); @@ -526,13 +526,13 @@ public class XmppConnectionService extends Service { } } - public void startForcingForegroundNotification() { - mForceForegroundService.set(true); + public void startOngoingVideoTranscodingForegroundNotification() { + mOngoingVideoTranscoding.set(true); toggleForegroundService(); } - public void stopForcingForegroundNotification() { - mForceForegroundService.set(false); + public void stopOngoingVideoTranscodingForegroundNotification() { + mOngoingVideoTranscoding.set(false); toggleForegroundService(); } @@ -1467,35 +1467,47 @@ public class XmppConnectionService extends Service { private void toggleForegroundService(final boolean force) { final boolean status; final OngoingCall ongoing = ongoingCall.get(); - if (force || mForceDuringOnCreate.get() || mForceForegroundService.get() || ongoing != null || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) { + final boolean ongoingVideoTranscoding = mOngoingVideoTranscoding.get(); + final int id; + if (force + || mForceDuringOnCreate.get() + || ongoingVideoTranscoding + || ongoing != null + || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) { final Notification notification; - final int id; if (ongoing != null) { notification = this.mNotificationService.getOngoingCallNotification(ongoing); id = NotificationService.ONGOING_CALL_NOTIFICATION_ID; startForegroundOrCatch(id, notification, true); - mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID); + } else if (ongoingVideoTranscoding) { + notification = this.mNotificationService.getIndeterminateVideoTranscoding(); + id = NotificationService.ONGOING_VIDEO_TRANSCODING_NOTIFICATION_ID; + startForegroundOrCatch(id, notification, false); } else { notification = this.mNotificationService.createForegroundNotification(); id = NotificationService.FOREGROUND_NOTIFICATION_ID; startForegroundOrCatch(id, notification, false); } - - if (!mForceForegroundService.get()) { - mNotificationService.notify(id, notification); - } + mNotificationService.notify(id, notification); status = true; } else { + id = 0; stopForeground(true); status = false; } - if (!mForceForegroundService.get()) { - mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID); + + for (final int toBeRemoved : + Collections2.filter( + Arrays.asList( + NotificationService.FOREGROUND_NOTIFICATION_ID, + NotificationService.ONGOING_CALL_NOTIFICATION_ID, + NotificationService.ONGOING_VIDEO_TRANSCODING_NOTIFICATION_ID), + i -> i != id)) { + mNotificationService.cancel(toBeRemoved); } - if (ongoing == null) { - mNotificationService.cancel(NotificationService.ONGOING_CALL_NOTIFICATION_ID); - } - Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off")); + Log.d( + Config.LOGTAG, + "ForegroundService: " + (status ? "on" : "off") + ", notification: " + id); } private void startForegroundOrCatch( @@ -1531,13 +1543,13 @@ public class XmppConnectionService extends Service { } public boolean foregroundNotificationNeedsUpdatingWhenErrorStateChanges() { - return !mForceForegroundService.get() && ongoingCall.get() == null && Compatibility.keepForegroundService(this) && hasEnabledAccounts(); + return !mOngoingVideoTranscoding.get() && ongoingCall.get() == null && Compatibility.keepForegroundService(this) && hasEnabledAccounts(); } @Override public void onTaskRemoved(final Intent rootIntent) { super.onTaskRemoved(rootIntent); - if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get() || ongoingCall.get() != null) { + if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mOngoingVideoTranscoding.get() || ongoingCall.get() != null) { Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated"); } else { this.logoutAndSave(false);