Install
Two dependency lines get you a working inspector. A third line on your
OkHttpClient turns on network capture. Everything after that is
optional.
Before you start
- minSdk 24 (Android 7.0). ANR and native crash reporting additionally need Android 11, because they read the OS
ApplicationExitInfoAPI. - OkHttp, if you want the Network and Mocks panels. Storage, WorkManager, Crashes and Runtime work without it.
- Build variants you can target separately — at minimum
debugandrelease. If you have a staging or internal-test variant, so much the better.
Step 1 — resolve from Maven Central
AppInspect is published to Maven Central, so in most projects this is already in
place. If your project declares repositories centrally, confirm
mavenCentral() is there.
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
Step 2 — add the dependency per variant
Add the full library to the builds you test, and the no-op stub to the build you
ship. Do not use plain implementation — that puts the inspector in
your production APK.
dependencies {
val appInspect = "io.github.suryansh1720001.appinspect"
// The full inspector, for builds your team tests
debugImplementation("$appInspect:appinspect:<latest-version>")
// A pass-through stub, so shared OkHttp code still compiles in release
releaseImplementation("$appInspect:appinspect-no-op:<latest-version>")
}
That is enough to have a working inspector. AppInspect initialises itself through
AndroidX Startup when the process starts, so there is nothing to add to your
Application class for the default setup.
If you have more than two variants
Gradle only generates debugImplementation and
releaseImplementation automatically. For your own variants, add the
configuration by name:
dependencies {
val group = "io.github.suryansh1720001.appinspect"
val inspector = "$group:appinspect:<latest-version>"
debugImplementation(inspector)
add("stagingImplementation", inspector)
add("internalTestImplementation", inspector)
releaseImplementation("$group:appinspect-no-op:<latest-version>")
}
Adding the artifact to a variant is not the same as letting it run there. The library also checks the build tier at runtime, and anything that is not debuggable stays off until you opt in explicitly. See enablement if your staging build is signed as a release build.
Step 3 — capture network traffic
Network capture is opt-in, because AppInspect never touches an
OkHttpClient you did not hand to it. Add the extension to your
builder, and add it last:
val client = OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.addInterceptor(loggingInterceptor)
.addAppInspectInterceptor() // last
.build()
The same code compiles in every variant. In release the extension comes from
appinspect-no-op and returns the builder untouched, so there is no
if (BuildConfig.DEBUG) to write.
Why the order matters
Two reasons, and both are easy to get wrong.
Short-circuit mocks skip whatever comes after. When a
SHORT_CIRCUIT rule fires, AppInspect returns a response without
calling chain.proceed(), so every interceptor registered after it
never runs. If your token-refresh interceptor sits after AppInspect, mocking will
quietly bypass it. Last means nothing of yours gets skipped.
Last is also where the request looks the way it really goes out — after your own interceptors have added their headers.
You get the real wire headers
addAppInspectInterceptor() actually installs two interceptors: an
application-level one that does the capturing and the mocking, and
AppInspectOkHttpWireHeaderInterceptor at the network level, which
only observes.
The second one exists because an application interceptor cannot see headers added
downstream of itself — an Authenticator retry, another network
interceptor, or OkHttp's own BridgeInterceptor, which adds
Host, User-Agent, Accept-Encoding,
Content-Length, Content-Type and Cookie.
Without it, an Authorization header attached later in the chain would
simply be missing from the panel. With it, what you see matches what Android
Studio's Network Inspector shows.
Where wire headers genuinely do not exist — a short-circuited mock, a fully cached response, a call that failed before reaching the network — the event falls back to the application-level headers. This also means captured request headers can contain credentials your calling code never set, which matters when you share an export: see the QA checklist.
Step 4 — check that it worked
- Install and launch a debug build.
- Shake the device firmly. The inspector should open full-screen. If shaking feels unreliable on your device, other entry points work just as well.
- Trigger a network call in your app, then open the Network panel. The call should be listed with its method, path, status and duration.
If the inspector opens but Network is empty, the interceptor is not on the client
that made the call — a second OkHttpClient built somewhere else is
the usual culprit. If nothing opens at all, the build is probably not debuggable;
check enablement.
Optional — take over the setup yourself
Auto-initialisation uses the default configuration. Call
AppInspect.install() from your Application instead when
you want to change something — which panels appear, what testers can edit,
which build tiers are allowed.
AppInspect.install(
application = this,
configuration = AppInspectConfiguration(
entryPoints = AppInspectEntryPoints(shakeToOpenEnabled = true),
panels = AppInspectPanels(mocksEnabled = true),
),
)
Every field is documented on the
configuration reference page.
AppInspect.initialize(configuration) still works and is kept for
compatibility, but prefer install().
One thing to guard by variant
appinspect-no-op deliberately mirrors only the OkHttp API surface.
AppInspect.install(), AppInspect.open() and the
long-press trigger helpers do not exist there, so calling them from shared code
breaks the release build.
Keep those calls in a debug-only source set, or behind your own no-op indirection. The interceptor line is the only part designed to live in shared code.
AppInspect can post a notification for each captured call, which is handy for watching traffic without keeping the inspector open. On Android 13 and newer your app has to request the runtime permission itself — see Network notifications.