Home Java NetworkOnMainThreadException — Move Network Off UI
Intermediate 5 min · September 23, 2026
Android NetworkOnMainThread Fix

NetworkOnMainThreadException — Move Network Off UI

Move network calls off Android's main thread with an Executor and Handler.

N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.

Follow
Production
production tested
September 23, 2026
last updated
1,905
articles · all by Naren
Before you start⏱ 12 min
  • Basic Android Activity lifecycle
  • Java threads and Runnables
  • Reading logcat stack traces
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • Android throws NetworkOnMainThreadException the moment code opens a socket, HTTP call, or DNS lookup on the main thread — StrictMode detectNetwork() enforces it
  • The ban exists because one slow request freezes every tap and scroll; block the main thread for 5 seconds and the system shows an ANR dialog
  • Fix it with an ExecutorService for the call plus a Handler on the main Looper for results — never with StrictMode.permitAll()
  • For repeated work use a shared pool or WorkManager; Kotlin code can use coroutines on Dispatchers.IO, the same idea with nicer syntax
  • Confirm with StrictMode penaltyDeath() in debug plus a throttled-network run — no crash and smooth UI means done
✦ Definition~90s read
What is Android NetworkOnMainThread Fix?

NetworkOnMainThreadException is Android's fail-fast refusal to run blocking network I/O on the main thread. It extends RuntimeException and is thrown by the platform networking stack — Socket, HttpURLConnection, InetAddress — the moment a blocking call executes on a thread carrying the main Looper.

Think of the main thread as a restaurant's single waiter.

StrictMode's detectNetwork() policy makes the violation loud in development; the underlying ban applies in every build.

The main thread is special because it owns the UI event loop. Sixteen milliseconds per frame, every tap, every animation, every lifecycle callback flows through it. Blocking calls are measured against that budget: disk I/O takes microseconds and is merely discouraged, but network I/O takes anywhere from 50 milliseconds to 30 seconds and is therefore forbidden outright.

No timeout setting makes it safe, because even a fast call occasionally hits a slow network.

Beginners often meet this exception alongside two confusions. First, it fires for the whole call chain, not just connect(): DNS resolution, TLS handshake, and reading the response stream are all network I/O and all throw. Second, it is unrelated to internet permission — a missing INTERNET permission throws SecurityException instead.

If you see NetworkOnMainThreadException, your permission is fine and your thread is wrong.

The fix direction follows from the design: move the blocking work to a background thread and marshal only the result back. ExecutorService plus Handler is the plain-Java expression of that pattern; coroutines, RxJava, and WorkManager are the same pattern with different scheduling.

The exception disappears as a side effect of correct threading, which is exactly how fail-fast guards are supposed to work.

Plain-English First

Think of the main thread as a restaurant's single waiter. Their job is taking orders, serving food, and smiling at tables — fast, constant motion. A network call is like sending that waiter across town to pick up ingredients. While they are gone, nobody gets served, tables pile up, and angry customers walk out. Android's rule is simple: hire a delivery driver (a background thread) for the trip across town, and let the waiter keep serving.

Every Android developer meets this crash early, usually five minutes after wiring a button to a real API. The code looks innocent: open an HttpURLConnection in onClick(), read the response, set the text. On the emulator it might even work once — then the app crashes with android.os.NetworkOnMainThreadException and a stack trace pointing straight at your click handler.

The crash feels arbitrary until you understand what the main thread does. It runs a loop that draws every frame, handles every tap, and processes every lifecycle callback. A network call parks that loop until the server answers. On fast Wi-Fi that pause is invisible; on a congested cell network it lasts seconds, and the entire phone appears frozen with your app on screen.

So Android refuses to let you do it. StrictMode watches for network operations on the main thread and the platform throws this exception instead of letting the UI hang. Beginners read it as red tape. Veterans read it as a guardrail that saved them from a flood of one-star reviews.

This article explains the ban, the ANR economics behind it, and the fix in plain Java: an ExecutorService for the work plus a Handler for delivering results. You will also learn why StrictMode.permitAll() is never the answer, and how WorkManager and coroutines fit the same pattern with different syntax.

StrictMode's Main-Thread Network Ban: How the Check Fires

StrictMode is a developer guardrail that watches the main thread for operations that should never run there: network calls, disk reads, and other blocking work. When detectNetwork() is enabled and code opens a socket on the main thread, the platform throws NetworkOnMainThreadException immediately instead of letting the UI hang until the server answers.

The check fires at the exact moment of the blocking call — connect(), getInputStream(), or even InetAddress.getByName() for DNS. That precision is why the stack trace is so useful: the frames above your code name the socket operation, and the first frame with your package name shows which UI callback started it. Read downward from the exception line and stop at your own method.

In debug builds you control the volume with penalties. penaltyLog() writes the violation to logcat, penaltyDeath() crashes so the bug cannot be ignored, and penaltyDialog() flashes a warning on screen. penaltyDeath() in debug is the setting that catches this class of bug on your desk, months before it becomes ANR data.

The dangerous escape hatch is StrictMode.permitAll(). It tells the guard to look away while the blocking call still runs on the main thread. The crash disappears, the freeze remains, and every future violation in that process hides too. Treat permitAll() in a diff the way you would treat a deleted test: a red flag, never a fix.

App.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectNetwork()
                    .penaltyLog()
                    .penaltyDeath()
                    .build());
        }
    }
}
⚠ Never Ship permitAll()
permitAll() disables the smoke detector while the fire keeps burning. Delete it and move the work — there is no production-safe use of permitAll().
📊 Production Insight
A team silenced this crash with permitAll() and shipped it. Crash-free sessions looked perfect while ANRs climbed to 2.1% over six days. Rule: alert on ANR rate per release, not just crashes — a silenced crash still freezes users.
🎯 Key Takeaway
StrictMode detectNetwork() turns main-thread network use into an instant crash. Use penaltyDeath() in debug to catch it early, and treat permitAll() as a bug, not a fix.

Why the UI Thread Can't Wait: ANR, Jank, and the 5-Second Rule

The main thread — also called the UI thread — runs a loop that draws a frame every 16 milliseconds, handles taps, and processes lifecycle callbacks. Anything that parks that loop pauses the entire app: scrolling stops, buttons stop responding, animations freeze mid-frame. Users perceive any stall past 100 milliseconds; past 5 seconds the system declares an ANR and offers to kill your app.

Network calls are uniquely hostile to this loop because their duration is unbounded. A disk read takes microseconds. A network round trip takes 50 milliseconds on good Wi-Fi, 3 seconds on a congested cell, and 30 seconds on a timeout. Putting that lottery on the UI thread means one unlucky user in a tunnel freezes the whole app while everyone on Wi-Fi sees nothing wrong.

Jank is the milder, more common symptom. Even a 200-millisecond call drops a dozen frames, and a scrolling list that fetches thumbnails inline will stutter constantly without ever crashing. Users rarely report jank — they just feel the app is cheap and switch to a competitor.

That is the rationale behind the ban. Android would rather crash your debug build today than let you ship an app that freezes on real networks tomorrow. The exception is fail-fast design: loud, immediate, and pointing at the exact line that must move.

📊 Production Insight
Pre-launch reports on a throttled GPRS profile caught 14 main-thread violations a team never saw on office Wi-Fi. Rule: run every release candidate on the slowest supported network before it reaches users.
🎯 Key Takeaway
The main thread must finish work in milliseconds. Network timing is unbounded, so it always belongs on a worker — the 5-second ANR limit is a ceiling, not a budget.

The Fix: ExecutorService for Work, Handler for Results

The canonical Java fix has two halves: a background thread does the network, and a Handler delivers the result to the main thread. An ExecutorService owns the worker threads so you never pay thread-creation costs per tap, and a Handler bound to the main Looper posts a Runnable that runs safely alongside the UI loop.

Keep the split strict. Everything that touches the network — openConnection(), connect(), reading the stream, parsing JSON — lives inside the worker Runnable. Everything that touches a View — setText(), showing a spinner, starting an Activity — lives inside the posted Runnable. Mixing the two halves recreates one of the two classic crashes.

Size the pool once and share it. A fixed pool of 2 to 4 threads handles typical app traffic; one pool per screen or per request leaks threads and memory. Create it in the Application class or a repository singleton, and shut it down in tests so suites do not hang on lingering non-daemon threads.

Always set timeouts. setConnectTimeout() and setReadTimeout() bound the worst case so a dead server costs you 8 seconds on a worker instead of an eternal hang. Timeouts plus the worker thread turn a network failure into a routine error string instead of a frozen app.

LoginActivity.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class LoginActivity extends Activity {
    private final ExecutorService netPool = Executors.newFixedThreadPool(4);
    private final Handler mainHandler = new Handler(Looper.getMainLooper());

    void onLoginClicked(String user, String pass) {
        netPool.execute(() -> {
            final String token = fetchToken(user, pass); // network here
            mainHandler.post(() -> showWelcome(token)); // UI here
        });
    }

    private String fetchToken(String user, String pass) {
        try {
            URL url = new URL("https://api.example.com/login");
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setConnectTimeout(8000);
            c.setReadTimeout(8000);
            try (InputStream in = c.getInputStream()) {
                return new String(in.readAllBytes(), StandardCharsets.UTF_8);
            } finally {
                c.disconnect();
            }
        } catch (IOException e) {
            return "error: " + e.getMessage();
        }
    }
}
📊 Production Insight
An app creating a newFixedThreadPool per request hit 240 live threads and started timing out from context-switch overhead. Rule: one shared pool per app, sized 2 to 4, created once in Application or a repository.
🎯 Key Takeaway
Network on a shared Executor, UI updates through a Handler on the main Looper. Set connect and read timeouts so failures stay fast and boring.

Modern Options: Futures, Coroutines, and WorkManager

Once the Executor pattern clicks, the modern options are variations on it. CompletableFuture.supplyAsync() with an explicit pool runs the call off-thread and orTimeout() caps the wait, while exceptionally() converts failures into fallback values without a single try-catch in the Activity. The Activity subscribes and posts to the UI only when the future completes.

Kotlin coroutines express the same idea with less ceremony: wrap the call in withContext(Dispatchers.IO) and the framework moves it to a shared background pool, then resumes on the main thread automatically. Dispatchers.IO exists precisely so network code never touches the UI loop. If your codebase is mixed Java and Kotlin, both approaches coexist fine behind a repository interface.

For work that must survive the user leaving the screen — uploads, sync, log shipping — reach for WorkManager. It runs the job on its own background executor, retries with backoff, and persists across process death and reboots. Foreground UI work stays on the Executor; deferrable work graduates to WorkManager.

Pick by lifetime, not fashion. A login call tied to a visible screen belongs on the Executor. A photo upload that must finish even if the user closes the app belongs in WorkManager. Both keep the main thread free, which is the only requirement that matters.

UserRepository.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class UserRepository {
    private final ExecutorService pool = Executors.newFixedThreadPool(4);

    public CompletableFuture<String> loadUserAsync(String id) {
        return CompletableFuture.supplyAsync(() -> downloadUser(id), pool)
                .orTimeout(10, TimeUnit.SECONDS)
                .exceptionally(e -> "fallback:" + e.getMessage());
    }

    private String downloadUser(String id) {
        try {
            URL url = new URL("https://api.example.com/users/" + id);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            try (InputStream in = c.getInputStream()) {
                return new String(in.readAllBytes(), StandardCharsets.UTF_8);
            } finally {
                c.disconnect();
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}
📊 Production Insight
A photo-upload feature retried on the UI thread survived code review because the retry lived in a helper. Rule: require WorkManager for any work that must outlive the screen, and flag retry loops in UI-layer reviews.
🎯 Key Takeaway
CompletableFuture, coroutines on Dispatchers.IO, and WorkManager all implement the same rule: network off the main thread. Choose by lifetime — visible-screen work versus must-finish work.

Reading the Trace and Reproducing on Demand

Reproduce deliberately instead of waiting for field reports. Enable penaltyDeathOnNetwork() in your debug Application class so any violation crashes instantly during normal tapping-through. Then walk every screen on an emulator with network speed set to GPRS: slow timing turns borderline calls into guaranteed crashes.

Read the resulting trace from the top. The exception line names NetworkOnMainThreadException, the next frames name the socket or HTTP internals, and the first frame containing your package pinpoints the UI callback. That frame is your fix site — move its network content to the worker, not the frame above or below.

Watch for violations hiding in helpers. Image loading, analytics, and auth-token refreshes often run inline in lifecycle methods where nobody expects network. detectAll() with penaltyLog() surfaces these quietly first; promote to death once the loud ones are fixed so stragglers cannot linger.

Pair StrictMode with the Play Console pre-launch report. Automated crawlers exercise your app on real devices and flag main-thread violations you never tap through. A clean pre-launch report plus zero StrictMode deaths in QA is the evidence that the fix held across the whole app, not just the login screen.

DebugApp.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DebugApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .penaltyDeathOnNetwork()
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedClosableObjects()
                .penaltyLog()
                .build());
    }
}
📊 Production Insight
QA walked 40 screens on a GPRS emulator profile and found 9 violations beyond the reported one, all in analytics helpers. Rule: make the throttled-network walkthrough part of the release checklist, not a one-off debug session.
🎯 Key Takeaway
penaltyDeathOnNetwork() plus a GPRS-throttled emulator turns hidden violations into instant, local crashes. Read the trace top-down to your first package frame.

Safe Migration Checklist: From permitAll() to Clean

Migrating safely means proving each screen clean rather than flipping a global switch. Start by deleting every permitAll() and penalty suppression, then run the StrictMode death build and fix violations one screen at a time. Each fix follows the same shape: worker does the call, Handler delivers the result, timeouts bound the worst case.

Guard the migration with automation. A lint check that fails the build on permitAll(), a debug Application class that always enables detectNetwork(), and a CI step that runs the pre-launch report turn a one-time cleanup into a permanent guarantee. Future code cannot regress what the build refuses to compile.

Handle rotation while you are there. An Executor task that posts to a dead Activity leaks the whole screen. Clear pending callbacks in onDestroy(), or deliver results through LiveData and ViewModel so the result survives rotation and only live observers react. The network fix and the lifecycle fix ship together because the crash report that follows a rotation leak looks confusingly similar.

Measure the outcome in ANRs, not crashes. A successful migration shows ANR rate falling under 0.5% and slow-frame percentage dropping in Android vitals. Those numbers are the proof your main thread is finally free — and they are the numbers your rating recovers on.

📊 Production Insight
A team tracking only crashes declared victory while ANRs stayed at 1.8%. Rule: put ANR rate and slow frames on the release dashboard next to crashes — main-thread health is measured in responsiveness, not just stack traces.
🎯 Key Takeaway
Delete suppressions, fix screen by screen with worker-plus-Handler, enforce with lint and CI, and confirm with ANR rate under 0.5% in vitals.
● Production incidentPOST-MORTEMseverity: high

A Login Refactor Froze 40,000 Phones After permitAll() Hid the Crash

Symptom
Users tapped login and the app froze for 6 to 12 seconds on mobile data, then showed the system ANR dialog offering to wait or close. Support received 3,100 frozen-login tickets in the first week. Crash reports stayed flat — the crash had been silenced, so only ANR telemetry and reviews told the story.
Assumption
The refactor only moved code between methods, so reviewers approved it without a StrictMode run. The team tested on office Wi-Fi where the login call answered in 90 milliseconds — far too fast to freeze visibly. Nobody ran the pre-launch report on a throttled network, and StrictMode was disabled in the debug build because its disk warnings were considered noise.
Root cause
A helper method that wrapped HttpURLConnection was inlined into the login Activity's onClick() during cleanup, putting the blocking call on the main thread. To silence the resulting crash, the developer added StrictMode.permitAll() in Application.onCreate(). The crash vanished but the blocking remained: on networks slower than 2 seconds per round trip, the main thread parked until the server answered, and after 5 seconds the system raised an ANR. Play Console recorded 12,400 ANRs in 6 days and the rating slid from 4.6 to 4.1.
Fix
The login call moved into a shared ExecutorService with the token posted back through a Handler on the main Looper, and the permitAll() lines were deleted. StrictMode detectNetwork() with penaltyDeath() was enabled in debug builds, and the release checklist gained a pre-launch run on a throttled network profile. The hotfix rolled out to all users within 48 hours and the ANR rate fell back to 0.12% the next day.
Key lesson
  • A refactor that moves code between methods can move blocking work onto the main thread — re-run StrictMode after every refactor that touches call paths, not just new features.
  • Office Wi-Fi hides main-thread blocking completely; gate releases on a throttled-network test where a 3-second round trip makes every violation obvious.
  • ANR rate is a release-blocking metric, not a vanity stat — alert on it the same day it moves, because each day of user pain costs roughly ten times the hotfix effort in lost ratings.
Production debug guideFive checks that separate a quick crash fix from a real main-thread cleanup.5 entries
Symptom · 01
Crash on button tap with NetworkOnMainThreadException in logcat
Fix
Run adb logcat -s AndroidRuntime System.err and reproduce the tap. You will see android.os.NetworkOnMainThreadException followed by frames naming your Activity method — that frame is the exact UI callback that opened the socket. Fix that call site first.
Symptom · 02
ANR dialogs on slow networks instead of a clean crash
Fix
Run adb shell dumpsys activity activities | grep -i anr and check the Play Console ANR rate for your release. If ANRs cluster on the same screen that makes network calls, the main thread is blocked there. Move those calls to an Executor and re-test on a throttled emulator network.
Symptom · 03
No crash locally but freezes reported from the field
Fix
Run grep -rn "permitAll" app/src/main/java and delete every hit. Then run ./gradlew :app:installDebug and retest; any hidden violation will now crash loudly in debug where you can fix it instead of freezing silently in production.
Symptom · 04
Fix works but the app stutters with hundreds of threads
Fix
Run adb shell dumpsys cpuinfo and look at thread counts in Android Studio's profiler while stress-testing. More than a hundred threads means a new Thread or pool per request. Replace them with one shared ExecutorService created in the Application class.
Symptom · 05
Need to prove every screen is clean before release
Fix
Run adb logcat -s StrictMode and exercise every screen on an emulator with network speed set to GPRS. Each DiskReadViolation or NetworkViolation line names the offending call. Treat every line as a bug and clear them before merge.
NetworkOnMainThreadException Causes Compared
Root CauseHow to ConfirmFixPrevention
HTTP call inside onClick() or lifecycle callbackStack trace shows android.os.NetworkOnMainThreadException with your Activity method in the framesMove the call into an Executor task; post results via HandlerEnable StrictMode detectNetwork() with penaltyDeath() in debug
StrictMode permitAll() hiding the violationGrep finds StrictMode.permitAll or ThreadPolicy.Builder().permitAll in sourceDelete the permit lines; move the work off-thread properlyAdd a lint rule or code-review checklist banning permitAll()
DNS or socket open hidden in a helper methodTrace frames pass through your helper into InetAddress.getByName or Socket.connectPush the whole helper call onto the background threadName helpers honestly (fetchUserSync) so callers see the blocking
Image or file download on the main threadStrictMode log or trace points at BitmapFactory.decodeStream over a URL streamDownload on a worker, decode there, post only the BitmapUse an image-loading library that owns its own executor
Retry loop with sleep on the UI threadANR trace shows main thread in Thread.sleep inside your retry methodRetry on the worker with backoff; deliver only the final outcomeNever call Thread.sleep on the main thread for any reason
⚙ Quick Reference
4 commands from this guide
FileCommand / CodePurpose
App.javapublic class App extends Application {StrictMode's Main-Thread Network Ban
LoginActivity.javapublic class LoginActivity extends Activity {The Fix
UserRepository.javapublic class UserRepository {Modern Options
DebugApp.javapublic class DebugApp extends Application {Reading the Trace and Reproducing on Demand

Key takeaways

1
NetworkOnMainThreadException means blocking network I/O ran on the UI thread
StrictMode caught it before users felt a freeze.
2
The main thread must never block
one slow request drops frames, and 5 stuck seconds produce an ANR dialog.
3
Fix it with an ExecutorService for the call plus a Handler on the main Looper for UI updates.
4
StrictMode.permitAll() hides the crash and ships the freeze
delete it, never commit it.
5
Use a shared pool or WorkManager for repeated and deferrable work instead of raw threads.
6
Prove the fix with StrictMode penaltyDeath() in debug and zero ANRs on a throttled network.

Common mistakes to avoid

5 patterns
×

Silencing StrictMode with permitAll() instead of moving the work

Symptom
Crash disappears in debug, but the app freezes on slow networks and ANR reports climb in the Play Console. Reviewers see the permitAll() call and reject the release.
Fix
Move the call into an ExecutorService task and post the result with a Handler on the main Looper. Keep every line that touches a View inside the posted Runnable. Delete the StrictMode.permitAll() lines entirely so the guard keeps protecting you.
×

Calling HttpURLConnection directly inside onClick() or onCreate()

Symptom
NetworkOnMainThreadException on every tap of the button, pointing at an Activity method. The stack trace names your click handler as the frame that opened the socket.
Fix
Restrict network code to doInBackground-style workers: Executor tasks, coroutine IO dispatchers, or WorkManager jobs. Let the UI layer only render results delivered through a Handler, LiveData, or callback.
×

Spawning a raw new Thread per request with no pool

Symptom
Crash is fixed but the app stutters under load, thread count climbs past 200 in Android Studio's profiler, and background requests start timing out from thread-creation overhead.
Fix
Create one shared ExecutorService (for example Executors.newFixedThreadPool(4)) in your Application class or repository, and shut it down in onTerminate() during tests. Never allocate a pool per request.
×

Updating a TextView from the background thread after the fix

Symptom
NetworkOnMainThreadException is gone, replaced by CalledFromWrongThreadException. The label never updates and logcat shows the view-access crash instead.
Fix
Post results with new Handler(Looper.getMainLooper()).post(...) or LiveData.postValue(). Only the worker thread touches the network; only the main thread touches Views. The crash for touching Views off-thread is a different exception, so respect both rules.
×

Testing only on fast office Wi-Fi with StrictMode off

Symptom
No crash on your desk, then thousands of ANRs from users on 3G within a week of rollout. Play Console shows the ANR rate jumping from 0.1% to over 2%.
Fix
Enable StrictMode detectNetwork() with penaltyDeath() in debug builds and run the app on a throttled network (emulator network speed set to GPRS). Fix every death before merging, and gate releases on zero ANRs in pre-launch reports.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What throws NetworkOnMainThreadException and how do you locate it?
Q02SENIOR
How does StrictMode help catch this before release?
Q03SENIOR
Why does Android ban network calls on the main thread?
Q04SENIOR
Why is StrictMode.permitAll() the wrong fix?
Q05SENIOR
Design background networking that survives rotation and process death.
Q01 of 05JUNIOR

What throws NetworkOnMainThreadException and how do you locate it?

ANSWER
It is a RuntimeException thrown when blocking network I/O runs on the main thread. You locate it by reading the stack trace: the top frames name the socket or HTTP call, and the first frame with your package name shows which UI callback started it. The fix is moving that call to a background thread.
FAQ · 6 QUESTIONS

Frequently Asked Questions

01
Does this crash happen in release builds or only in debug?
02
Do Kotlin coroutines still need special handling for this?
03
Is StrictMode.permitAll() ever acceptable?
04
How is this different from an ANR?
05
How do I update the UI after the background call finishes?
06
Can reading the response stream trigger it too?
N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Drawn from code that ran under real load.

Follow
Verified
production tested
September 23, 2026
last updated
1,905
articles · all by Naren
🔥

That's Android. Mark it forged?

5 min read · try the examples if you haven't

Previous
Java ArithmeticException Fix
1 / 3 · Android
Next
Android Cleartext HTTP Fix