From 777ef609ff4eeb73aa04c8a1380b2860ed5eabb0 Mon Sep 17 00:00:00 2001 From: adbenitez Date: Wed, 7 Jan 2026 17:13:36 +0100 Subject: [PATCH] avoid crash in FetchForegroundService.onCreate() --- .../service/FetchForegroundService.java | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/thoughtcrime/securesms/service/FetchForegroundService.java b/src/main/java/org/thoughtcrime/securesms/service/FetchForegroundService.java index dd8a3cd0e..12544a9d9 100644 --- a/src/main/java/org/thoughtcrime/securesms/service/FetchForegroundService.java +++ b/src/main/java/org/thoughtcrime/securesms/service/FetchForegroundService.java @@ -40,24 +40,7 @@ public final class FetchForegroundService extends Service { } } catch (Exception e) { Log.w(TAG, "Failed to start foreground service: " + e + ", fetching in background."); - // According to the documentation https://firebase.google.com/docs/cloud-messaging/android/receive, - // we need to handle the message within 20s, and the time window may be even shorter than 20s, - // so, use 10s to be safe. - fetchingSynchronously = true; - if (ApplicationContext.getDcAccounts().backgroundFetch(10)) { - // The background fetch was successful, but we need to wait until all events were processed. - // After all events were processed, we will get DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE, - // and stop() will be called. - synchronized (STOP_NOTIFIER) { - while (fetchingSynchronously) { - try { - // The `wait()` needs to be enclosed in a while loop because there may be - // "spurious wake-ups", i.e. `wait()` may return even though `notifyAll()` wasn't called. - STOP_NOTIFIER.wait(); - } catch (InterruptedException ex) {} - } - } - } + fetchSynchronously(); } } @@ -87,14 +70,40 @@ public final class FetchForegroundService extends Service { .setSmallIcon(R.drawable.notification_permanent) .build(); - startForeground(NotificationCenter.ID_FETCH, notification); + try { + startForeground(NotificationCenter.ID_FETCH, notification); - Util.runOnAnyBackgroundThread(() -> { - Log.i(TAG, "Starting fetch"); - if (!ApplicationContext.getDcAccounts().backgroundFetch(300)) { // as startForeground() was called, there is time - FetchForegroundService.stop(this); - } // else we stop FetchForegroundService on DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE - }); + Util.runOnAnyBackgroundThread(() -> { + Log.i(TAG, "Starting fetch"); + if (!ApplicationContext.getDcAccounts().backgroundFetch(300)) { // as startForeground() was called, there is time + FetchForegroundService.stop(this); + } // else we stop FetchForegroundService on DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE + }); + } catch (Exception e) { + Log.w(TAG, "Error calling startForeground(): " + e + ", fetching in background."); + fetchSynchronously(); + } + } + + private static void fetchSynchronously() { + // According to the documentation https://firebase.google.com/docs/cloud-messaging/android/receive, + // we need to handle the message within 20s, and the time window may be even shorter than 20s, + // so, use 10s to be safe. + fetchingSynchronously = true; + if (ApplicationContext.getDcAccounts().backgroundFetch(10)) { + // The background fetch was successful, but we need to wait until all events were processed. + // After all events were processed, we will get DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE, + // and stop() will be called. + synchronized (STOP_NOTIFIER) { + while (fetchingSynchronously) { + try { + // The `wait()` needs to be enclosed in a while loop because there may be + // "spurious wake-ups", i.e. `wait()` may return even though `notifyAll()` wasn't called. + STOP_NOTIFIER.wait(); + } catch (InterruptedException ex) {} + } + } + } } @Override