Tapping through the launcher to reach a specific screen for a repeated test is slow and inconsistent. The am (activity manager) command lets a test script jump straight to an activity, fire a deep link, or send a broadcast, the same way the Android framework itself would when an app receives an intent.
adb shell am start -n com.example.app/.MainActivity
The -n flag takes a component name in package/activity form. When the activity class is in a subpackage rather than the app's root package, the full class path is required instead of the shorthand dot-prefix:
adb shell am start -n com.example.app/com.example.app.ui.SettingsActivity
If the exact activity class is unknown, dump the app's manifest-declared activities via package manager:
adb shell dumpsys package com.example.app | grep -A 1 "android.intent.action.MAIN"
Alternatively, launch the app normally through the launcher, then check which activity is currently in the foreground:
adb shell dumpsys activity activities | grep mResumedActivity
adb shell am start -a android.intent.action.VIEW -d "myapp://profile/42"
This is the standard way to test a custom URI scheme or App Link handler without needing another app or a browser to trigger it. If the target app declares the scheme in its manifest correctly, Android resolves the intent exactly as it would from a tapped link, including showing a disambiguation dialog if more than one app claims the same scheme.
adb shell am start -n com.example.app/.DetailActivity \
--es user_id "42" \
--ei retry_count 3 \
--ez debug_mode true
The flag prefix indicates the extra's type: --es for a String, --ei for an int, --ez for a boolean, --el for a long, and --ef for a float. Getting the type flag wrong is the most common reason an activity crashes immediately on launch with a ClassCastException reading the intent extras — the value arrives as the wrong type rather than failing to arrive at all.
adb shell am broadcast -a com.example.app.ACTION_REFRESH
Useful for triggering a BroadcastReceiver directly during development without waiting for whatever system event would normally fire it, such as simulating a connectivity change without actually toggling airplane mode:
adb shell am broadcast -a android.net.conn.CONNECTIVITY_CHANGE
Note that Android 8.0 and later restrict many implicit broadcasts for battery reasons; an app targeting a recent API level may need the broadcast sent with an explicit component name rather than just an action string for the receiver to actually fire.
For repeatable cold-start testing, kill the app's process before each launch so the activity does not simply resume an existing task:
adb shell am force-stop com.example.app
adb shell am start -n com.example.app/.MainActivity
Without the force-stop step, a script measuring cold-start time will silently measure a warm resume instead after the first run, producing numbers that look better than what a real user opening the app from a fully-killed state would experience.
An am start call targeting an activity that is not exported in the app's manifest fails with a SecurityException: Permission Denial on non-rooted devices, by design — this is the same protection that stops other apps on the device from launching internal screens directly. There is no ADB flag that bypasses this; the activity has to be exported (or the device rooted) for the command to work at all.
adb shell am startservice -n com.example.app/.SyncService
On Android 8.0 and later, background service start restrictions mean this only reliably works while the app itself is in the foreground or recently used; a service started this way against a fully backgrounded app on a newer OS version can be immediately stopped by the system before it finishes whatever it was meant to do, which is expected platform behavior rather than a command failure.
A separate but related tool, am instrument, runs an app's instrumented test suite directly from the command line rather than launching a regular activity:
adb shell am instrument -w com.example.app.test/androidx.test.runner.AndroidJUnitRunner
This is the same mechanism Gradle's connectedAndroidTest task uses under the hood, so running it manually is a useful way to reproduce a CI test failure locally with the exact same invocation the build server used, rather than guessing at equivalent IDE-triggered test runs.