lingochamp/FileDownloader · error · IllegalThreadStateException

Sorry, FileDownloader can not block the main thread…

Error message

Sorry, FileDownloader can not block the main thread, because the system is also  callbacks ServiceConnection#onServiceConnected method in the main thread.

What it means

FileDownloadLine.wait() blocks the current thread until the download service binds; because Android invokes ServiceConnection#onServiceConnected on the main thread, waiting on the main thread would deadlock. The library therefore throws IllegalThreadStateException if wait (via startForeground/getSoFar/getTotal/getStatus on pending calls) is invoked from the main thread.

Solutions

  1. Call these methods from a background thread (worker thread, executor, or coroutine on IO dispatcher).
  2. Ensure the service is already bound before calling, or use the async callback-based APIs (listener-based start).
  3. Wrap in try-catch only as a guard; prefer not invoking from the main thread at all.

Example fix

// before
FileDownloader.getImpl().startForeground(false); // on main thread

// after
new Thread(() -> FileDownloader.getImpl().startForeground(false)).start();
Defensive patterns

Strategy: validation

Validate before calling

if (Looper.myLooper() == Looper.getMainLooper()) {
    throw new IllegalStateException("call off the main thread");
}
FileDownloader.getImpl().startForeground(false);

Type guard

boolean isMainThread() { return Looper.myLooper() == Looper.getMainLooper().getThread() || Looper.myLooper() == Looper.getMainLooper(); }

Prevention

When it happens

Trigger: Calling FileDownloader.getImpl().startForeground(false) (or getSoFar/getTotal/getStatus that need service binding) from an Activity/UI thread before the service is connected.

Common situations: Calling startForeground in Application.onCreate or Activity without a background thread; querying progress synchronously in onCreate.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of lingochamp/FileDownloader@6237a8cac1 (2026-09-08). Data as JSON: /api/errors/4e47bce0a92e68e4. Report an issue: GitHub.

Appendix: source

Thrown at library/src/main/java/com/liulishuo/filedownloader/FileDownloadLine.java:154

            }
        };

        wait(subscriber);

        return (byte) subscriber.getValue();
    }

    private void wait(final ConnectSubscriber subscriber) {
        final ConnectListener connectListener = new ConnectListener(subscriber);

        //noinspection SynchronizationOnLocalVariableOrMethodParameter
        synchronized (connectListener) {
            FileDownloader.getImpl().bindService(connectListener);

            if (!connectListener.isFinished()) {

                if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
                    throw new IllegalThreadStateException("Sorry, FileDownloader can not block the "
                            + "main thread, because the system is also  callbacks "
                            + "ServiceConnection#onServiceConnected method in the main thread.");
                }

                try {
                    connectListener.wait(200 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class ConnectListener implements Runnable {
        private boolean mIsFinished = false;
        private final ConnectSubscriber mSubscriber;

        ConnectListener(ConnectSubscriber subscriber) {

View on GitHub (pinned to 6237a8cac1)