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