Inspect your own Android app

Trust the Busymate CA in your own app so its HTTPS decrypts on an unrooted Android phone — the network security config Android requires.

To decrypt HTTPS from an app you're developing on an unrooted Android phone, that app has to trust the Busymate certificate authority (CA). Android doesn't grant that trust automatically — you add a small network security config to your own app so it accepts user-installed CAs. This is a one-line-of-XML change you make in your debug build, and it's the same step Proxyman and Charles ask for.

Why this is needed

When you install the Busymate CA on an Android phone, it lands in the user certificate store. On a non-rooted device, that store is only honoured by apps that explicitly opt in.

Since Android 7.0 (API level 24), every app that targets API 24 or higher ignores user-installed CAs by default and trusts only the system store. System browsers and curl-style tools still honour the user CA, so their traffic decrypts out of the box — but your own app won't, no matter how correctly the CA is installed. Busymate DevTools presents a certificate signed by its CA; your app sees a CA it was told not to trust and closes the connection.

The fix is to tell your app, in debug builds only, that the user store is trusted. You do that with a network security config.

Busymate CAuser storeSystem browser,curl, opted-in appAny app, API 24+,default configdecryptsstays opaque

Rooted device? You don't need any of this. On a rooted phone you can install the Busymate CA into the system store, which every app trusts — see Trust the CA. The steps below are only for unrooted phones, where the system store is read-only.

Step 1 — add a network security config

Create the file res/xml/network_security_config.xml in your app (the standard location is app/src/main/res/xml/network_security_config.xml).

The recommended form scopes user-CA trust to debug builds only, so your production app is never weakened. Android applies a <debug-overrides> block only when the app is built debuggable, and strips it from release builds entirely:

xml
<network-security-config>
  <debug-overrides>
    <trust-anchors>
      <certificates src="user" />
      <certificates src="system" />
    </trust-anchors>
  </debug-overrides>
</network-security-config>

Keep the system anchor alongside user — without it, your debug build would trust only user-installed CAs and every ordinary HTTPS call (to hosts you're not proxying) would start failing.

Alternative — base-config (use with care)

<debug-overrides> covers almost every case and is the safe default. If you need user-CA trust somewhere it doesn't reach — for example a build variant that isn't marked debuggable, or tooling that inspects the config directly — you can trust the user store through <base-config> instead:

xml
<network-security-config>
  <base-config cleartextTrafficPermitted="true">
    <trust-anchors>
      <certificates src="user" />
      <certificates src="system" />
    </trust-anchors>
  </base-config>
</network-security-config>

Never ship this to production. A <base-config> that trusts user applies to every build, including release. That permanently weakens your app against anyone who can get a CA onto a victim's device. If you use the base-config form, gate it to a debug-only source set (src/debug/res/xml/…) so the release build never carries it. When in doubt, prefer <debug-overrides> — it can't leak into release.

Step 2 — reference it from the manifest

Point your app's <application> tag at the config you just created, in AndroidManifest.xml:

xml
<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >

If you scoped the config to a debug-only source set, put this android:networkSecurityConfig attribute in the corresponding debug manifest (src/debug/AndroidManifest.xml) so it's merged only into debug builds.

Step 3 — rebuild, install the CA, and capture

  1. Rebuild and install the debug build of your app on the phone (./gradlew installDebug, or Run from Android Studio). The user-CA trust only exists in the newly built binary — reinstalling the old build won't pick it up.
  2. Install the Busymate CA on the device if you haven't already: download the PEM from https://busymate.net/ca.pem and add it under Settings → Security → Encryption & credentials → Install a certificate → CA certificate. Full walkthrough: Trust the CA.
  3. Point the phone at the proxy and start capture — see Connect a client.
  4. Confirm it decrypts. Open your app and trigger a request. Its HTTPS calls now appear in the dashboard feed with readable headers and decrypted bodies, instead of an opaque tunnel.

If the app's traffic still shows up encrypted, the config didn't take effect — recheck that you rebuilt the debug build, that the manifest reference resolves to the file, and that the CA is installed in the user store.

Security callout

User-CA trust is a debugging posture, not a shipping one. Trusting the user certificate store lets any locally-installed CA decrypt your app's traffic — exactly what you want while debugging on a device you control, and exactly what you never want in the hands of your users. Only ever enable it for debug builds, and reach for <debug-overrides> first: because Android compiles it out of release builds, there is no way for it to escape into production. Never trust the user store from a <base-config> that a release build can carry.

A worked example

Busymate DevTools' own Android app uses precisely this pattern — a <debug-overrides> network security config at the standard app/src/main/res/xml/network_security_config.xml path, referenced from its debug manifest — so its own debug builds can be inspected the same way. If you're wiring this up for the first time, that config is a faithful template to copy.

Next

Ask your mate