HdcClient

Struct HdcClient 

Source
pub struct HdcClient { /* private fields */ }
Expand description

HDC client for communicating with HDC server

Implementations§

Source§

impl HdcClient

Source

pub fn new(address: impl Into<String>) -> Self

Create a new HDC client (not connected)

Source

pub async fn connect(address: impl Into<String>) -> Result<Self>

Connect to HDC server

Source

pub fn channel_id(&self) -> u32

Get the channel ID

Source

pub fn is_connected(&self) -> bool

Check if handshake is complete

Source

pub async fn send_command(&mut self, command: &str) -> Result<()>

Send raw command string to server

This is used for simple commands like “list targets”, “shell ls”, etc.

Source

pub async fn read_response(&mut self) -> Result<Vec<u8>>

Read response from server

Source

pub async fn read_response_string(&mut self) -> Result<String>

Read response as string

Source

pub async fn shell(&mut self, cmd: &str) -> Result<String>

Execute a shell command and return output

If a device has been selected via connect_device(), the command will be executed on that device (the device ID is set in the channel’s connectKey during handshake). Otherwise, HDC server will return an error asking to specify a device.

Note: Each shell command uses up the current channel. After execution, the connection is automatically re-established if a device was connected.

Source

pub async fn list_targets(&mut self) -> Result<Vec<String>>

List connected devices/targets

Source

pub async fn connect_device(&mut self, device_id: &str) -> Result<()>

Connect to a specific device

This re-establishes the connection with the specified device ID in the handshake. After calling this, all commands will be executed on the specified device.

Source

pub async fn check_server(&mut self) -> Result<String>

Check server version

Source

pub async fn target_command( &mut self, device_id: &str, cmd: &str, ) -> Result<String>

Execute a command on a specific device

This is a convenience method that:

  1. Connects to the specified device (re-handshake with connectKey)
  2. Executes the command

Note: This changes the client’s current device setting.

Source

pub async fn shell_on_device( &mut self, device_id: &str, cmd: &str, ) -> Result<String>

Execute a shell command on a specific device (convenience method)

This connects to the device and executes: shell <cmd>

Source

pub async fn close(&mut self) -> Result<()>

Close the connection

Source

pub async fn fport( &mut self, local: ForwardNode, remote: ForwardNode, ) -> Result<String>

Create a port forward (fport)

Forward local traffic to remote device.

§Example
// Forward local TCP 8080 to device TCP 8081
client.fport(ForwardNode::Tcp(8080), ForwardNode::Tcp(8081)).await?;
Source

pub async fn rport( &mut self, remote: ForwardNode, local: ForwardNode, ) -> Result<String>

Create a reverse port forward (rport)

Reserve remote traffic to local host.

§Example
// Forward device TCP 8080 to local TCP 8081
client.rport(ForwardNode::Tcp(8080), ForwardNode::Tcp(8081)).await?;
Source

pub async fn fport_list(&mut self) -> Result<Vec<String>>

List all forward/reverse tasks

Note: This command does not require a device connection. It lists forwards across all devices.

Source

pub async fn fport_remove(&mut self, task_str: &str) -> Result<String>

Remove a forward/reverse task by task string

Note: This command does not require a device connection.

§Example
client.fport_remove("tcp:8080 tcp:8081").await?;
Source

pub async fn install( &mut self, paths: &[&str], options: InstallOptions, ) -> Result<String>

Install application package(s) to device

§Arguments
  • paths - Single or multiple package paths (.hap, .hsp) or directories
  • options - Install options (replace, shared)
§Example
let opts = InstallOptions::new().replace(true);
client.install(&["app.hap"], opts).await?;
Source

pub async fn uninstall( &mut self, package: &str, options: UninstallOptions, ) -> Result<String>

Uninstall application package from device

§Arguments
  • package - Package name to uninstall
  • options - Uninstall options (keep_data, shared)
§Example
let opts = UninstallOptions::new().keep_data(true);
client.uninstall("com.example.app", opts).await?;
Source

pub async fn hilog(&mut self, args: Option<&str>) -> Result<String>

Display device logs using hilog

This method streams logs from the device. The log stream will continue until the connection is closed or an error occurs.

§Arguments
  • args - Optional arguments for hilog command (e.g., “-h” for help, “-t app” for app logs)
§Example
// Display all logs
let logs = client.hilog(None).await?;
println!("{}", logs);

// Display only app logs
let app_logs = client.hilog(Some("-t app")).await?;
println!("{}", app_logs);
Source

pub async fn hilog_stream<F>( &mut self, args: Option<&str>, callback: F, ) -> Result<()>
where F: FnMut(&str) -> bool,

Stream hilog output continuously with a callback

This method streams logs from the device and calls the provided callback for each log chunk received. The stream continues until an error occurs or the callback returns false.

§Arguments
  • args - Optional arguments for hilog command
  • callback - Function to call for each log chunk. Return false to stop streaming.
§Example
client.hilog_stream(None, |log_chunk| {
    print!("{}", log_chunk);
    true // Continue streaming
}).await?;
Source

pub async fn wait_for_device(&mut self) -> Result<String>

Wait for any device to connect

This command blocks until at least one device is connected. If a device is already connected, it returns immediately.

§Example
// Wait for any device
let device = client.wait_for_device().await?;
println!("Device connected: {}", device);
Source

pub async fn monitor_devices<F>( &mut self, interval: Duration, callback: F, ) -> Result<()>
where F: FnMut(&[String]) -> bool,

Monitor device list changes with a callback

This function continuously polls the device list and calls the callback when changes are detected. The polling interval can be configured.

Note: HDC doesn’t have a native “track-devices” command like adb, so this implementation uses polling to detect changes. Each poll creates a new connection to ensure reliability.

§Arguments
  • interval - Polling interval (recommended: 1-3 seconds)
  • callback - Function called when device list changes. Return false to stop monitoring.
§Example
client.monitor_devices(Duration::from_secs(2), |devices| {
    println!("Device list changed:");
    for device in devices {
        println!("  - {}", device);
    }
    true // Continue monitoring
}).await?;
Source

pub async fn file_send( &mut self, local_path: &str, remote_path: &str, options: FileTransferOptions, ) -> Result<String>

Send file to device

Transfer a file from local path to remote device path.

§Arguments
  • local_path - Local file path to send
  • remote_path - Remote device path destination
  • options - File transfer options (timestamp, sync, compress, etc.)
§Example
let opts = FileTransferOptions::new()
    .hold_timestamp(true)
    .compress(true);
client.file_send("test.txt", "/data/local/tmp/test.txt", opts).await?;
Source

pub async fn file_recv( &mut self, remote_path: &str, local_path: &str, options: FileTransferOptions, ) -> Result<String>

Receive file from device

Transfer a file from remote device path to local path.

§Arguments
  • remote_path - Remote device file path to receive
  • local_path - Local destination path
  • options - File transfer options (timestamp, sync, compress, etc.)
§Example
let opts = FileTransferOptions::new().hold_timestamp(true);
client.file_recv("/data/local/tmp/test.txt", "test.txt", opts).await?;

Trait Implementations§

Source§

impl Drop for HdcClient

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more