Tapping a link from a chat app is a bad way to test deep links, because the messenger often rewrites or swallows the URL before your app sees it. The terminal removes all of that: you hand the URL straight to Android's activity manager and watch what happens, with the same Intent your app would receive in production. The command is adb shell am start.

The command Google gives you

The canonical form from the Android documentation is a single line:

adb shell am start -W -a android.intent.action.VIEW -d "example://gizmos" com.example.android

That fires a VIEW intent for example://gizmos, waits for the launch to finish, and targets com.example.android. Swap in your own URI and package and you have a working test. The ADB Command Generator builds the whole line from a form if you would rather not type it.

am start, flag by flag

The flags that matter for deep link testing, from the activity manager reference:

  • -a <action> · the intent action, always android.intent.action.VIEW for deep links. Declare it once.
  • -d  · the data URI, which is your deep link itself. Once.
  • -c <category> · an intent category, such as android.intent.category.BROWSABLE, to reproduce how a browser dispatches the link.
  • -n <component> · a fully qualified component, like com.example.app/.MainActivity, for an explicit intent targeting one activity.
  • -e | --es <key> <value> · a string extra.
  • --ez <key> <value> · a boolean extra. --ei for an integer extra.
  • -f <flags> · intent flags, as supported by setFlags().
  • -W · wait for the launch to complete, so am reports the result instead of returning immediately.

Worked example: a custom scheme

For myapp://product/42, let the system resolve it the way a tap would:

adb shell am start -W \
  -a android.intent.action.VIEW \
  -d "myapp://product/42"

If one app handles the scheme, it launches. If the URI is unregistered, you get Error: Activity not started, unable to resolve Intent, which is a useful answer: the scheme is not registered the way you think. To rule out the resolver, target the activity explicitly with -n:

adb shell am start -W \
  -a android.intent.action.VIEW \
  -d "myapp://product/42" \
  -n com.example.app/.ProductActivity

Worked example: an HTTPS App Link

For a verified App Link, reproduce a browser-style dispatch by adding the BROWSABLE category and letting the system pick the target:

adb shell am start -W \
  -a android.intent.action.VIEW \
  -c android.intent.category.BROWSABLE \
  -d "https://example.com/product/42"

If your domain is verified, your app opens. If Chrome opens instead, the link is not verifying, and the App Link troubleshooting guide is the next stop. Forcing the package or -n launches your app regardless of verification, handy for confirming the activity handles the URL while verification is still broken.

Passing extras and flags

Deep links sometimes arrive with extras. Attach them with the typed flags:

adb shell am start -W \
  -a android.intent.action.VIEW \
  -d "myapp://checkout" \
  --es coupon "SUMMER" \
  --ez guest true \
  --ei step 2

Always wrap the URI in double quotes. A shell will interpret &, ?, #, and spaces in an unquoted URL and mangle your query string before adb sees it. If your link carries an encoded payload, confirm what reaches the device is what you intended, because a missed layer of URL encoding is a classic "the link works but the parameters are empty" bug.

Reading the output

With -W, am prints a short status block. Status: ok with a TotalTime means the activity launched. Error: Activity not started, unable to resolve Intent means nothing matched, which points at the scheme, host, or path. Warning: Activity not started, its current task has been brought to the front means the target was already on screen, which is fine. Pair this with adb logcat to see what your app does with the Intent; the Logcat Filter Builder narrows the output to your process.

When more than one device is connected

With an emulator and a phone both attached, adb refuses with error: more than one device/emulator. List them and target one with -s:

adb devices
adb -s emulator-5554 shell am start -W \
  -a android.intent.action.VIEW \
  -d "myapp://product/42"

The -s flag goes on adb itself, before shell. Worth baking into any test script, since unqualified commands stop working the moment a second device appears.

Common questions

Why does am start say "unable to resolve Intent"?

No installed activity has an intent filter matching the action, scheme, host, and path you passed. Either the app is not installed, the scheme is misspelled, or the path does not match the pathPrefix or pathPattern in the manifest. Build the filter with the Intent-Filter Generator and confirm the URI falls inside the pattern it declares.

Can I test an iOS Universal Link with adb?

No. adb talks to Android only. The iOS equivalent is xcrun simctl openurl booted "https://example.com/path" for the simulator, or xcrun devicectl for a real device. The Deep Link Tester covers both platforms with a QR code.

Do I have to pass the package name?

No. Leaving it off lets the system resolve the link the way a real tap would. Adding the package or an explicit -n component forces your app to handle the URI even when verification or disambiguation would send it elsewhere, useful for proving the activity logic in isolation.

Keep reading

Official docs


Last updated · June 2026 · by Belchior, mobile engineer