{"record":{"id":"4e47bce0a92e68e4","repo":"lingochamp/FileDownloader","slug":"sorry-filedownloader-can-not-block-the-main-threa","errorCode":null,"errorMessage":"Sorry, FileDownloader can not block the main thread, because the system is also  callbacks ServiceConnection#onServiceConnected method in the main thread.","messagePattern":"Sorry, FileDownloader can not block the main thread, because the system is also  callbacks ServiceConnection#onServiceConnected method in the main thread\\.","errorType":"exception","errorClass":"IllegalThreadStateException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/liulishuo/filedownloader/FileDownloadLine.java","lineNumber":154,"sourceCode":"            }\n        };\n\n        wait(subscriber);\n\n        return (byte) subscriber.getValue();\n    }\n\n    private void wait(final ConnectSubscriber subscriber) {\n        final ConnectListener connectListener = new ConnectListener(subscriber);\n\n        //noinspection SynchronizationOnLocalVariableOrMethodParameter\n        synchronized (connectListener) {\n            FileDownloader.getImpl().bindService(connectListener);\n\n            if (!connectListener.isFinished()) {\n\n                if (Thread.currentThread() == Looper.getMainLooper().getThread()) {\n                    throw new IllegalThreadStateException(\"Sorry, FileDownloader can not block the \"\n                            + \"main thread, because the system is also  callbacks \"\n                            + \"ServiceConnection#onServiceConnected method in the main thread.\");\n                }\n\n                try {\n                    connectListener.wait(200 * 1000);\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n    }\n\n    static class ConnectListener implements Runnable {\n        private boolean mIsFinished = false;\n        private final ConnectSubscriber mSubscriber;\n\n        ConnectListener(ConnectSubscriber subscriber) {","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/lingochamp/FileDownloader/blob/6237a8cac174bcc916e4342b14ab1ab72a5768d4/library/src/main/java/com/liulishuo/filedownloader/FileDownloadLine.java#L136-L172","documentation":"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.","triggerScenarios":"Calling FileDownloader.getImpl().startForeground(false) (or getSoFar/getTotal/getStatus that need service binding) from an Activity/UI thread before the service is connected.","commonSituations":"Calling startForeground in Application.onCreate or Activity without a background thread; querying progress synchronously in onCreate.","solutions":["Call these methods from a background thread (worker thread, executor, or coroutine on IO dispatcher).","Ensure the service is already bound before calling, or use the async callback-based APIs (listener-based start).","Wrap in try-catch only as a guard; prefer not invoking from the main thread at all."],"exampleFix":"// before\nFileDownloader.getImpl().startForeground(false); // on main thread\n\n// after\nnew Thread(() -> FileDownloader.getImpl().startForeground(false)).start();","handlingStrategy":"validation","validationCode":"if (Looper.myLooper() == Looper.getMainLooper()) {\n    throw new IllegalStateException(\"call off the main thread\");\n}\nFileDownloader.getImpl().startForeground(false);","typeGuard":"boolean isMainThread() { return Looper.myLooper() == Looper.getMainLooper().getThread() || Looper.myLooper() == Looper.getMainLooper(); }","tryCatchPattern":null,"preventionTips":["Never call blocking FileDownloader APIs from the UI thread.","Use RxFileDownloader/Coroutine extensions that schedule on IO.","Prefer listener-based async APIs over polling getSoFar/getTotal."],"tags":["android","main-thread","deadlock","service-binding"],"backgroundTag":"unsupported-operation","analyzedSha":"6237a8cac174bcc916e4342b14ab1ab72a5768d4","analyzedAt":"2026-09-08T23:50:48.168Z","contentChangedAt":"2026-09-08T23:50:48.168Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}