cd /news/developer-tools/scrcpy-integration-in-a-tauri-app-an… · home topics developer-tools article
[ARTICLE · art-13176] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

scrcpy Integration in a Tauri App — Android Screen Mirroring on Mac

The article describes how to integrate scrcpy, an open-source Android screen mirroring tool, into a Tauri app for Mac. It covers launching scrcpy from Rust code, bundling it as a universal binary within the app's resources, detecting when the mirror window closes, and supporting multiple Android devices via ADB serial selection. The author tested the implementation on an 8-year-old MacBook Air while shipping seven Mac apps as a solo developer.

read2 min views41 publishedMay 24, 2026

All tests run on an 8-year-old MacBook Air. All results from shipping 7 Mac apps as a solo developer. No sponsored opinion. HiyokoKit includes Android remote control via scrcpy. Launching and managing scrcpy from a Tauri app has specific challenges. Here's how I handle it. What scrcpy is scrcpy is an open-source tool that mirrors and controls an Android device screen over ADB. It's the best free option for Android screen mirroring on Mac — fast, low latency, no app required on the device. Launching scrcpy from Rust

rustuse std::process::{Command, Child};
use std::sync::Mutex;
pub struct ScrcpyProcess {

child: Option,

}
impl ScrcpyProcess {
pub fn start(

&mut self, device_serial: &str, max_size: u32, bit_rate: &str,

) -> Result<(), AppError> {
let child = Command::new("scrcpy")
.args([
"--serial", device_serial,
"--max-size", &max_size.to_string(),
"--video-bit-rate", bit_rate,
"--window-title", "Android Mirror",
"--no-audio",
])
.spawn()
.map_err(|e| AppError::Scrcpy(e.to_string()))?;
self.child = Some(child);
Ok(())
}
pub fn stop(&mut self) {
if let Some(mut child) = self.child.take() {
child.kill().ok();
}
}
pub fn is_running(&mut self) -> bool {
if let Some(child) = &mut self.child {
child.try_wait().map(|s| s.is_none()).unwrap_or(false)
} else {

false

}
}
}

Bundling scrcpy scrcpy needs to be available on the user's machine or bundled with your app. I bundle it in app resources as a universal binary: json{

"bundle": {
"resources": [

"bin/scrcpy", "bin/adb"

]
}
}

At runtime, get the resource path: rustlet scrcpy_path = app_handle

.path()
.resource_dir()
.unwrap()
.join("bin/scrcpy");

Detecting when scrcpy exits scrcpy exits when the user closes the mirror window. Detect this to update your UI: rust// Poll in background tokio::spawn(async move { loop {

tokio::time::sleep(Duration::from_secs(1)).await;
let running = {
let mut proc = scrcpy_state.lock().unwrap();
proc.is_running()
};
if !running {
app_handle.emit("scrcpy-stopped", ()).ok();
break;
}
}
});

Multiple device support scrcpy's --serial flag selects a specific device when multiple are connected. Get the serial from adb devices and pass it explicitly:

rustasync fn get_device_serial() -> Result {
let output = Command::new("adb")
.args(["devices"])
.output()

.await?;

let stdout = String::from_utf8_lossy(&output.stdout);
stdout.lines()
.skip(1)
.find(|l| l.contains("device"))
.and_then(|l| l.split_whitespace().next())
.map(|s| s.to_string())
.ok_or(AppError::Device("No device found".into()))
}
If this was useful, a ❤️ helps more than you'd think — thanks!

Hiyoko PDF Vault → https://hiyokomtp.lemonsqueezy.com/checkout X → @hiyoyok

── more in #developer-tools 4 stories · sorted by recency
── more on @scrcpy 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/scrcpy-integration-i…] indexed:0 read:2min 2026-05-24 ·