pub struct AdbClient { /* private fields */ }Expand description
Client wrapping adb invocations.
Construction is cheap — internally just an adb binary path resolved
via PATH lookup at command-spawn time. No persistent state.
Implementations§
Source§impl AdbClient
impl AdbClient
Sourcepub fn with_binary(binary: impl Into<String>) -> Self
pub fn with_binary(binary: impl Into<String>) -> Self
Build with an explicit adb binary path (useful for tests or
non-PATH SDK installs).
Sourcepub async fn devices(&self) -> Result<Vec<AdbDevice>, AdbError>
pub async fn devices(&self) -> Result<Vec<AdbDevice>, AdbError>
adb devices -l — list all attached devices/emulators.
Sourcepub async fn install(
&self,
serial: &str,
apk_path: &Path,
) -> Result<(), AdbError>
pub async fn install( &self, serial: &str, apk_path: &Path, ) -> Result<(), AdbError>
adb -s <serial> install -r <apk> — install (or upgrade) an apk.
Sourcepub fn spawn_shell(&self, serial: &str, cmd: &[&str]) -> Result<Child, AdbError>
pub fn spawn_shell(&self, serial: &str, cmd: &[&str]) -> Result<Child, AdbError>
Spawn adb -s <serial> shell <cmd...> and hand back the child rather
than waiting for it.
For device commands that run until stopped — screenrecord is the
one. The caller owns the child, and how it ends matters: screenrecord
only finalizes a playable mp4 when it gets SIGINT, so killing the
child outright leaves a file with no moov atom.
Sourcepub async fn pull(
&self,
serial: &str,
remote: &str,
local: &Path,
) -> Result<(), AdbError>
pub async fn pull( &self, serial: &str, remote: &str, local: &Path, ) -> Result<(), AdbError>
adb -s <serial> pull <remote> <local> — copy a file off the device.
Sourcepub async fn push(
&self,
serial: &str,
local: &Path,
remote: &str,
) -> Result<(), AdbError>
pub async fn push( &self, serial: &str, local: &Path, remote: &str, ) -> Result<(), AdbError>
adb -s <serial> push <local> <remote> — copy a file onto the device.
Sourcepub async fn broadcast(
&self,
serial: &str,
action: &str,
data: Option<&str>,
) -> Result<(), AdbError>
pub async fn broadcast( &self, serial: &str, action: &str, data: Option<&str>, ) -> Result<(), AdbError>
adb -s <serial> shell am broadcast -a <action> [-d <data>].
Note that result=0 is the ordinary answer — it means the broadcast
was delivered and nothing set a result code, not that anything failed.
Sourcepub async fn uninstall(
&self,
serial: &str,
package: &str,
) -> Result<(), AdbError>
pub async fn uninstall( &self, serial: &str, package: &str, ) -> Result<(), AdbError>
adb -s <serial> uninstall <pkg> — uninstall a package.
Sourcepub async fn start_activity(
&self,
serial: &str,
package: &str,
activity: &str,
extras: &[(&str, &str)],
) -> Result<(), AdbError>
pub async fn start_activity( &self, serial: &str, package: &str, activity: &str, extras: &[(&str, &str)], ) -> Result<(), AdbError>
adb -s <serial> shell am start -n <pkg>/<activity> [args] — launch
app’s activity. Returns nothing on success.
Sourcepub async fn force_stop(
&self,
serial: &str,
package: &str,
) -> Result<(), AdbError>
pub async fn force_stop( &self, serial: &str, package: &str, ) -> Result<(), AdbError>
adb -s <serial> shell am force-stop <pkg> — force-stop a package.
Sourcepub async fn screenshot(&self, serial: &str) -> Result<Vec<u8>, AdbError>
pub async fn screenshot(&self, serial: &str) -> Result<Vec<u8>, AdbError>
adb -s <serial> shell screencap -p — capture device screen as PNG.
Returns raw PNG bytes via stdout.
Sourcepub async fn forward(
&self,
serial: &str,
host_port: u16,
device_port: u16,
) -> Result<(), AdbError>
pub async fn forward( &self, serial: &str, host_port: u16, device_port: u16, ) -> Result<(), AdbError>
adb -s <serial> forward tcp:<host> tcp:<device> — set up port
forwarding from host loopback to device port.
Sourcepub async fn unforward(
&self,
serial: &str,
host_port: u16,
) -> Result<(), AdbError>
pub async fn unforward( &self, serial: &str, host_port: u16, ) -> Result<(), AdbError>
adb -s <serial> forward --remove tcp:<host> — remove a forward.
Sourcepub async fn shell(
&self,
serial: &str,
cmd: &[&str],
) -> Result<String, AdbError>
pub async fn shell( &self, serial: &str, cmd: &[&str], ) -> Result<String, AdbError>
adb -s <serial> shell <cmd...> — generic shell exec, returns stdout.
Runs on the device. For the emulator console — geo, sms,
rotate and friends — use Self::emu: those are adb’s own
subcommands, and asking the device’s shell for them finds nothing.
Sourcepub async fn emu(&self, serial: &str, cmd: &[&str]) -> Result<String, AdbError>
pub async fn emu(&self, serial: &str, cmd: &[&str]) -> Result<String, AdbError>
adb -s <serial> emu <cmd...> — the emulator console, returns stdout.
A different channel from Self::shell. adb shell emu geo fix …
looks plausible but asks the device for a program named emu — it
answers sh: emu: inaccessible or not found and exits 127.
setLocation shipped that way, so it always failed.
The console reports differently from the shell, and that is why this
method exists rather than a call site. adb shell propagates the
device command’s exit status (measured: shell 'exit 42' → 42), but
adb emu does not — it answers OK, or KO: <reason>, and exits
0 either way (measured: a bad argument gives
KO: argument 'x' is not a number, exit 0). So the exit code carries
nothing here and stdout carries everything; KO is translated into an
error, because nobody downstream would think to look for it.
Emulator-only, as the name says. A physical device has no console, which is no loss: smix is simulator-only by charter.
Sourcepub async fn pm_grant(
&self,
serial: &str,
package: &str,
permission: &str,
) -> Result<(), AdbError>
pub async fn pm_grant( &self, serial: &str, package: &str, permission: &str, ) -> Result<(), AdbError>
adb -s <serial> shell pm grant <pkg> <android.permission.X>.
Sourcepub async fn pm_clear(
&self,
serial: &str,
package: &str,
) -> Result<(), AdbError>
pub async fn pm_clear( &self, serial: &str, package: &str, ) -> Result<(), AdbError>
adb -s <serial> shell pm clear <pkg> — wipe the app’s data.
Measured: this also reverts the package’s runtime permissions to their default. There is no host-side way to wipe the data alone, so a caller who wants only the files loses the grants with them.
Sourcepub async fn runtime_permissions_granted(
&self,
serial: &str,
package: &str,
) -> Result<Vec<String>, AdbError>
pub async fn runtime_permissions_granted( &self, serial: &str, package: &str, ) -> Result<Vec<String>, AdbError>
The runtime permissions <pkg> currently holds.
Read from dumpsys package, which is the only host-side view of
them: pm reset-permissions exists but reverts every app on the
device, including whatever the runner was granted to do its job.