1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use std::future::Future;
use std::path::Path;
use std::process::Child;
use std::process::Stdio;
use tokio::io::{AsyncBufReadExt, BufReader}; // 确保导入所需的trait
use tokio::process::Command;
pub trait ADBCmdTrait {
fn new(cmd: String, is_shell: bool) -> Self;
fn create_cmd(self) -> Command;
async fn run_async<F>(&self, args: Vec<String>, fnc: F)
where
F: FnMut(String) -> String + 'static;
fn run(&self, args: Vec<String>) -> Result<String, String>;
fn get_var_arg(self, args: Vec<String>) -> impl Future<Output = bool>;
fn get_file_path(path: &str) -> Result<String, String>;
}
/// ADBCmd allows you to execute adb commands asynchronously.
#[derive(Debug, Clone)]
pub struct ADBCmd {
cmd: String,
is_shell: bool,
}
impl ADBCmdTrait for ADBCmd {
fn new(cmd: String, is_shell: bool) -> Self {
ADBCmd { cmd, is_shell }
}
fn create_cmd(self) -> Command {
let mut command = Command::new(self.cmd);
if self.is_shell {
command.arg("shell");
}
command
}
// run_async runs the given adb command asynchronously.
/// ```no_run
///
/// use std::process::Command;
///
/// use ADB::cmd::ADBCmd;
///
/// let adb_cmd = ADBCmd::new();
/// #[tokio::main]
/// adb_cmd.run_async(vec!["devices".to_string()], |line| {
/// println!("{}", line);
/// line
/// }).await;
/// ```
async fn run_async<F>(&self, args: Vec<String>, mut fnc: F)
where
F: FnMut(String) -> String + 'static,
{
let mut cmd = <ADBCmd as Clone>::clone(&self)
.create_cmd()
.arg("/c")
.args(args)
.stdout(std::process::Stdio::piped()) // 将标准输出重定向到管道
.spawn() // 启动子进程
.expect("failed to execute command");
if let Some(stdout) = cmd.stdout.take() {
let reader = BufReader::new(stdout);
let mut lines = reader.lines();
while let Ok(Some(line)) = lines.next_line().await {
let _result = fnc(line);
// 这里你可以直接使用 `result`,或者根据需要做进一步的处理
}
}
}
/// run runs the given adb command synchronously.
/// ```no_run
/// use std::process::Command;
///
/// use ADB::cmd::ADBCmd;
///
/// let adb_cmd = ADBCmd::new("cmd".to_string(),false);
///
/// let result = adb_cmd.run(vec!["devices".to_string()]);
/// ```
fn run(&self, args: Vec<String>) -> Result<String, String> {
let mut output = std::process::Command::new("cmd");
output.arg("/C");
output.arg(&self.cmd);
if self.is_shell {
output.arg("shell".to_string());
}
output.args(args);
let child = output
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.map_err(|err| format!("Failed command : {}", err))?;
let stdout: String = String::from_utf8_lossy(&child.stdout).to_string();
let stderr: String = String::from_utf8_lossy(&child.stderr).to_string();
if !stderr.is_empty() {
Err(stderr)
} else {
Ok(stdout)
}
}
/// Get variable on command
/// ```no_run
/// let mut arg=String::from("mmi");
/// let exec_args=vec![];
/// let args= vec![
/// "ls".to_string(),
/// "/system/bin/sxrmmi".to_string()
/// ]
/// let _prefix= ADBCmd::new("adb",false).get_var_arg(args);
/// if _prefix.is_ok(){
/// arg = format!("{}{}","sxr".to_string(),arg);
/// }else{
/// arg = format!("{}{}","ssnwt".to_string(),arg);
/// }
/// exec_args.push(arg);
/// exec_args.push("stop".to_string());
/// let res= ADBCmd::new("adb",false).run(exec_args);
///
/// ```
async fn get_var_arg(self, args: Vec<String>) -> bool {
let res = self.run(args);
match res {
Ok(_) => true,
Err(_) => false,
}
}
/// 获取文件路径
/// ```no_run
/// let res= ADBCmd::new("adb",false).get_file_path("./resources/file.xml");
/// ```
fn get_file_path(path: &str) -> Result<String, String> {
let mut _custom_path = Path::new(path).canonicalize();
match _custom_path {
Ok(p) => Ok(p.as_os_str().to_string_lossy().to_string()),
Err(_err) => Err(format!("The file path does not exist or is incorrect")),
}
}
}