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}