Skip to main content

radb/
lib.rs

1//! # ADB Utils - Android Debug Bridge Utilities for Rust
2//!
3//! A comprehensive Rust library for interacting with Android devices through ADB (Android Debug Bridge).
4//! This library provides both synchronous and asynchronous interfaces for device management, file operations,
5//! shell command execution, and more.
6//!
7//! ## Features
8//!
9//! - **Dual API Support**: Both blocking and async/await interfaces
10//! - **Device Management**: Connect, disconnect, and manage multiple devices
11//! - **File Operations**: Push, pull, list, and manipulate files on devices
12//! - **Shell Commands**: Execute shell commands with streaming support
13//! - **Screen Operations**: Screenshots, input simulation, and screen control
14//! - **App Management**: Install, uninstall, start, and stop applications
15//! - **Network Operations**: Port forwarding, reverse forwarding, WiFi control, and network information
16//! - **System Information**: Device properties, Android version, hardware info
17//! - **Logging**: Logcat streaming and filtering
18//!
19//! ## Quick Start
20//!
21//! ### Blocking API
22//!
23//! ```rust,no_run
24//! # #[cfg(feature = "blocking")]
25//! # mod blocking_example {
26//! use radb::prelude::*;
27//!
28//! fn main() -> AdbResult<()> {
29//!     // Connect to ADB server
30//!     let mut client = AdbClient::connect("127.0.0.1:5037")?;
31//!     
32//!     // Get device list
33//!     let devices = client.list_devices()?;
34//!     let mut device = devices.into_iter().next().unwrap();
35//!     
36//!     // Execute shell command
37//!     let result = device.shell(["echo", "Hello, ADB!"])?;
38//!     println!("Output: {}", result);
39//!     
40//!     // Take screenshot
41//!     let screenshot = device.screenshot()?;
42//!     println!("Screenshot: {}x{}", screenshot.width(), screenshot.height());
43//!
44//!     Ok(())
45//! }
46//! # }
47//! ```
48//!
49//! ### Async API
50//!
51//! ```rust,no_run
52//! # #[cfg(feature = "tokio_async")]
53//! # mod async_example {
54//! use radb::prelude::*;
55//! use radb::AdbResult;
56//! #[tokio::main]
57//! async fn main() -> AdbResult<()> {
58//!     // Connect to ADB server
59//!     let mut client = AdbClient::connect("127.0.0.1:5037").await?;
60//!     
61//!     // Get device list
62//!     let devices = client.list_devices().await?;
63//!     let mut device = devices.into_iter().next().unwrap();
64//!     
65//!     // Execute shell command
66//!     let result = device.shell(["echo", "Hello, ADB!"]).await?;
67//!     println!("Output: {}", result);
68//!     
69//!     // Stream logcat
70//!     let mut logcat = Box::pin(device.logcat(true, None).await?);
71//!     while let Some(line) = logcat.as_mut().next().await {
72//!         println!("Log: {}", line?);
73//!     }
74//!
75//!     Ok(())
76//! }
77//! # }
78//! ```
79//!
80//! ## Feature Flags
81//!
82//! - `blocking`: Enable blocking/synchronous API (default)
83//! - `tokio_async`: Enable async/await API with Tokio runtime
84//!
85//! `blocking` and `tokio_async` share command construction, response parsing,
86//! and ADB sync frame handling. The runtime-specific layers only handle
87//! connection setup, IO, and `await` adaptation.
88//!
89//! ## Error Handling
90//!
91//! The library uses a comprehensive error system with specific error types:
92//!
93//! ```rust,no_run
94//! use radb::prelude::*;
95//!
96//! let result: AdbResult<String> = Err(AdbError::command_failed(
97//!     "shell invalid_command",
98//!     "not found",
99//! ));
100//!
101//! match result {
102//!     Ok(output) => println!("Success: {}", output),
103//!     Err(AdbError::CommandFailed { command, reason }) => {
104//!         eprintln!("Command '{}' failed: {}", command, reason);
105//!     }
106//!     Err(AdbError::DeviceNotFound { serial }) => {
107//!         eprintln!("Device '{}' not found", serial);
108//!     }
109//!     Err(e) => eprintln!("Other error: {}", e),
110//! }
111//! ```
112
113// Core modules
114pub mod beans;
115pub mod client;
116pub mod errors;
117pub mod protocols;
118pub mod sync_protocol;
119pub mod utils;
120
121// Re-exports for convenience
122pub use client::{AdbClient, AdbDevice};
123pub use errors::{AdbError, AdbResult};
124
125// Prelude module for common imports
126pub mod prelude {
127    //! Common imports for ADB utilities
128    //!
129    //! This module re-exports the most commonly used types and traits.
130    //! Import this module to get started quickly:
131    //!
132    //! ```rust
133    //! use radb::prelude::*;
134    //! ```
135
136    pub use crate::beans::{AdbCommand, AppInfo, FileInfo, ForwardItem, NetworkType};
137    pub use crate::client::{AdbClient, AdbDevice};
138    pub use crate::errors::{AdbError, AdbResult, AdbResultExt};
139    pub use crate::utils::{get_free_port, start_adb_server};
140
141    // Re-export commonly used external types
142    #[cfg(feature = "tokio_async")]
143    pub use futures_util::StreamExt;
144
145    #[cfg(feature = "blocking")]
146    pub use std::net::TcpStream;
147
148    #[cfg(feature = "tokio_async")]
149    pub use tokio::net::TcpStream;
150}
151
152// Convenient type aliases
153pub type Result<T> = std::result::Result<T, AdbError>;
154
155// Version and metadata
156pub const VERSION: &str = env!("CARGO_PKG_VERSION");
157pub const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
158pub const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
159
160// Library information
161pub mod info {
162    //! Library metadata and version information
163
164    /// Get library version
165    pub fn version() -> &'static str {
166        crate::VERSION
167    }
168
169    /// Get library description
170    pub fn description() -> &'static str {
171        crate::DESCRIPTION
172    }
173
174    /// Get library authors
175    pub fn authors() -> &'static str {
176        crate::AUTHORS
177    }
178
179    /// Print library information
180    pub fn print_info() {
181        println!("ADB Utils v{}", version());
182        println!("Description: {}", description());
183        println!("Authors: {}", authors());
184    }
185}
186
187// Utilities module with public helpers
188pub mod util {
189    //! Utility functions for ADB operations
190
191    pub use crate::utils::*;
192
193    /// Check if ADB server is running
194    pub fn is_adb_server_running() -> bool {
195        use std::net::TcpStream;
196        TcpStream::connect("127.0.0.1:5037").is_ok()
197    }
198
199    /// Start ADB server if not running
200    pub fn ensure_adb_server() -> crate::AdbResult<()> {
201        if !is_adb_server_running() {
202            start_adb_server();
203            // Wait a bit for server to start
204            std::thread::sleep(std::time::Duration::from_millis(500));
205        }
206        Ok(())
207    }
208
209    /// Get ADB server version (convenience function)
210    #[cfg(feature = "blocking")]
211    pub fn get_adb_server_version() -> crate::AdbResult<String> {
212        let mut client = crate::AdbClient::connect("127.0.0.1:5037")?;
213        client.server_version()
214    }
215
216    /// Get ADB server version (async convenience function)
217    #[cfg(feature = "tokio_async")]
218    pub async fn get_adb_server_version_async() -> crate::AdbResult<String> {
219        let mut client = crate::AdbClient::connect("127.0.0.1:5037").await?;
220        client.server_version().await
221    }
222}
223
224// Feature-specific modules
225#[cfg(feature = "blocking")]
226pub mod blocking {
227    //! Blocking/synchronous API
228    //!
229    //! This module contains the blocking versions of ADB operations.
230    //! Use this when you don't need async/await functionality.
231
232    #[allow(unused_imports)]
233    pub use crate::client::adb_client::blocking_impl::*;
234    #[allow(unused_imports)]
235    pub use crate::client::adb_device::blocking_impl::*;
236    pub use crate::protocols::blocking::AdbProtocol;
237}
238
239#[cfg(feature = "tokio_async")]
240pub mod r#async {
241    //! Asynchronous API
242    //!
243    //! This module contains the async versions of ADB operations.
244    //! Use this when you need async/await functionality with Tokio.
245
246    #[allow(unused_imports)]
247    pub use crate::client::adb_client::async_impl::*;
248    #[allow(unused_imports)]
249    pub use crate::client::adb_device::async_impl::*;
250    pub use crate::protocols::tokio_async::AdbProtocol;
251}
252
253// Builder pattern for common operations
254pub mod builder {
255    //! Builder patterns for complex operations
256
257    use crate::prelude::*;
258
259    /// Builder for ADB client configuration
260    pub struct AdbClientBuilder {
261        addr: Option<String>,
262        timeout: Option<std::time::Duration>,
263    }
264
265    impl AdbClientBuilder {
266        /// Create a new client builder
267        pub fn new() -> Self {
268            Self {
269                addr: None,
270                timeout: None,
271            }
272        }
273
274        /// Set ADB server address
275        pub fn addr<S: Into<String>>(mut self, addr: S) -> Self {
276            self.addr = Some(addr.into());
277            self
278        }
279
280        /// Set connection timeout
281        pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
282            self.timeout = Some(timeout);
283            self
284        }
285
286        /// Build the client (blocking version)
287        #[cfg(feature = "blocking")]
288        pub fn build(self) -> AdbResult<AdbClient> {
289            let addr = self.addr.unwrap_or_else(|| "127.0.0.1:5037".to_string());
290            AdbClient::connect(addr)
291        }
292
293        /// Build the client (async version)
294        #[cfg(feature = "tokio_async")]
295        pub async fn build_async(self) -> AdbResult<AdbClient> {
296            let addr = self.addr.unwrap_or_else(|| "127.0.0.1:5037".to_string());
297            AdbClient::connect(addr).await
298        }
299    }
300
301    impl Default for AdbClientBuilder {
302        fn default() -> Self {
303            Self::new()
304        }
305    }
306}
307
308// Testing utilities (only available in tests)
309#[cfg(test)]
310pub mod test_utils {
311    //! Testing utilities for ADB operations
312
313    use std::fmt::Debug;
314
315    use crate::prelude::*;
316
317    /// Setup test environment
318    pub fn setup_test_env() {
319        crate::utils::start_adb_server();
320        std::thread::sleep(std::time::Duration::from_millis(500));
321    }
322
323    /// Get test device (if available)
324    #[cfg(feature = "blocking")]
325    pub fn get_test_device() -> Option<AdbDevice<impl std::net::ToSocketAddrs + Clone + Debug>> {
326        let mut client = AdbClient::connect("127.0.0.1:5037").ok()?;
327        client.list_devices().ok()?.into_iter().next()
328    }
329
330    /// Get test device (async version)
331    #[cfg(feature = "tokio_async")]
332    pub async fn get_test_device_async(
333    ) -> Option<AdbDevice<impl tokio::net::ToSocketAddrs + Clone + Debug>> {
334        let mut client = AdbClient::connect("127.0.0.1:5037").await.ok()?;
335        client.list_devices().await.ok()?.into_iter().next()
336    }
337}
338
339// Macros for common operations
340#[macro_export]
341macro_rules! adb_shell {
342    ($device:expr, $($arg:expr),+) => {
343        $device.shell([$($arg),+])
344    };
345}
346
347#[macro_export]
348macro_rules! adb_expect_device {
349    ($client:expr) => {
350        $client
351            .list_devices()?
352            .into_iter()
353            .next()
354            .ok_or_else(|| $crate::AdbError::device_not_found("No devices found"))?
355    };
356}
357
358pub use anyhow;
359pub use log;
360
361// Conditional exports based on features
362#[cfg(feature = "tokio_async")]
363pub use tokio;
364
365#[cfg(feature = "blocking")]
366pub use std::net;
367
368// Documentation examples
369#[cfg(doctest)]
370doc_comment::doctest!("../README.md");
371
372// Feature compatibility checks
373#[cfg(all(feature = "blocking", feature = "tokio_async"))]
374compile_error!("Cannot use both 'blocking' and 'tokio_async' features simultaneously");
375
376#[cfg(not(any(feature = "blocking", feature = "tokio_async")))]
377compile_error!("Must enable either 'blocking' or 'tokio_async' feature");
378
379// Platform-specific optimizations
380#[cfg(target_os = "android")]
381compile_error!("This library is not intended to run on Android devices");
382
383// Export the main ADB namespace for convenience
384pub mod adb {
385    //! Main ADB namespace with all core functionality
386
387    pub use crate::beans::*;
388    pub use crate::client::*;
389    pub use crate::errors::*;
390    pub use crate::prelude::*;
391}