Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RemoteServiceException: Bad notification for startForeground: java.util.ConcurrentModificationException #17386

Open
Tracked by #17370
david-allison opened this issue Nov 7, 2024 · 2 comments

Comments

@david-allison
Copy link
Member

david-allison commented Nov 7, 2024

https://ankidroid.org/acra/app/1/bug/248923/report/d9019a48-73c0-446c-8df9-06fc00b9e046

android.app.RemoteServiceException: Bad notification for startForeground: java.util.ConcurrentModificationException
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1807)
	at android.os.Handler.dispatchMessage(Handler.java:105)
	at android.os.Looper.loop(Looper.java:164)
	at android.app.ActivityThread.main(ActivityThread.java:6759)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)

Logcat

--------- beginning of main
11-06 09:56:10.086 I/AnkiDroid(14268): deck filter: 5 ()
--------- beginning of crash
@david-allison david-allison changed the title https://ankidroid.org/acra/app/1/bug/248923/report/d9019a48-73c0-446c-8df9-06fc00b9e046 RemoteServiceException: Bad notification for startForeground: java.util.ConcurrentModificationException Nov 7, 2024
@david-allison
Copy link
Member Author

I suspect this can't be reproduced given the logcat

@david-allison david-allison added this to the 2.19.2 release milestone Nov 7, 2024
@mikehardy
Copy link
Member

Possibly interesting:

  • every single one of these is Android 8.0.0
  • this exception is thrown by the system as it attempts to receive a broadcast and post a foreground service notification, perhaps in relation to auto-sync on startup or similar. When there is a problem, one part of Android posts a "crash" notification to the other part, with more information sometimes https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/RemoteServiceException.java#117
  • we're not getting the "more information" source part, however ConcurrentModificationException and Android 8 and foreground-service-notification post failure can only mean one of a few things:

In either case, a quick look through notification channel create+update on startup and/or foreground service notification post+update on startup and hardening them against failures like this, perhaps with a retry, could work

Or we could just ignore it...

Gemini AI had these "insights" from the Play dashboard entry for the crash:

Gemini may display inaccurate information, so double-check its responses
Summary

The app crashed because it attempted to start a foreground service with a notification that caused a ConcurrentModificationException. This exception typically occurs when multiple threads try to modify a collection (like a list or map) simultaneously without proper synchronization. In this case, it seems like the notification object was being modified while the system was trying to use it to start the foreground service, leading to the Bad notification for startForeground error. This usually happens within the application code, specifically during the creation or modification of the notification object.

Potential Solutions

Synchronize Notification Access: The most likely cause is concurrent access to the notification or its builder object. Ensure that all modifications to the notification, including its properties and actions, are performed within a synchronized block or using thread-safe data structures. This prevents multiple threads from modifying the notification simultaneously.
// Example using synchronized block
private final Object notificationLock = new Object();

// ... within the service's onStartCommand() or other relevant method

synchronized (notificationLock) {
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
            // ... set notification properties
            .setContentTitle("Example")
            .setContentText("Notification");

    startForeground(NOTIFICATION_ID, builder.build());
}
Copy the Notification Builder: If different parts of your code are modifying the same NotificationCompat.Builder instance, create a copy of the builder before modifying it. This isolates the changes to a specific thread and prevents conflicts with the foreground service start-up process.
// Example creating a copy of the builder
NotificationCompat.Builder originalBuilder = // ... your existing builder

NotificationCompat.Builder builderCopy = new NotificationCompat.Builder(this, CHANNEL_ID);
builderCopy.setContentTitle(originalBuilder.mContentTitle)
// ... copy other necessary properties from originalBuilder

// ... modify builderCopy as needed

startForeground(NOTIFICATION_ID, builderCopy.build());

Review Custom Notification Actions: If you're using custom PendingIntent objects for notification actions (e.g., buttons within the notification), verify that these PendingIntents are created correctly and are not causing any threading issues. Ensure that any data used within these PendingIntents, such as Intent extras, is accessed in a thread-safe manner. Consider using immutable data structures or defensive copies when passing data to PendingIntents to avoid modification after creation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants