This page covers how the scrcpy-server Android component is compiled and packaged into the binary that gets pushed to a device at runtime. The server is a Java application run on Android via app_process; it is not a conventional APK. For how the client locates and launches the server at runtime, see ADB and Server Management. For the client-side build configuration, see Client Build Configuration.
The server build produces a single file named scrcpy-server, which is a ZIP archive (JAR/zip format) containing classes.dex — the DEX bytecode that Android's runtime can execute. Two independent build paths exist:
| Build Method | Tool Chain | Recommended For |
|---|---|---|
| Gradle | Android Gradle Plugin | Regular development |
build_without_gradle.sh | aidl, javac, dx/d8 | CI environments without Gradle, manual inspection |
Both paths compile the same Java source files in server/src/main/java/ and the same AIDL definitions in server/src/main/aidl/.
The top-level meson.build16-18 provides a compile_server option, but the actual server build is always performed by Gradle or the shell script; Meson only wraps it as a subproject step.
Sources: meson.build1-18 server/build.gradle1-34 server/build_without_gradle.sh1-116
The Gradle build is configured in server/build.gradle1-34 The plugin applied is the standard Android application plugin.
| Setting | Value | Purpose |
|---|---|---|
compileSdk | 36 | API level used for compilation |
minSdkVersion | 21 | Lowest Android version supported |
targetSdkVersion | 36 | Target API level |
versionCode | 30304 | Numeric version identifier |
versionName | "3.3.4" | Human-readable version string |
minifyEnabled | false | No ProGuard/R8 code shrinking |
buildConfig | true | Generates BuildConfig.java with DEBUG and VERSION_NAME |
aidl | true | Enables AIDL compilation step |
See server/build.gradle3-27 for the full android {} block.
The Android Gradle Plugin handles the full pipeline automatically:
server/src/main/aidl/ to Java stubs.BuildConfig.java.javac..class files to DEX format via d8.The AndroidManifest.xml at server/src/main/AndroidManifest.xml1-2 is intentionally minimal — a bare <manifest /> tag — because scrcpy-server is not a real Android application and is never installed as an APK.
Sources: server/build.gradle1-34 server/src/main/AndroidManifest.xml1-2
build_without_gradle.sh)server/build_without_gradle.sh1-116 is a self-contained shell script that replicates the Gradle pipeline using raw Android SDK tooling.
| Variable | Default | Description |
|---|---|---|
ANDROID_HOME | (required) | Path to Android SDK root |
ANDROID_PLATFORM | 36 | Android platform version |
ANDROID_BUILD_TOOLS | 36.0.0 | Build tools version string |
BUILD_DIR | build_manual | Output directory |
Manual Build Pipeline
Sources: server/build_without_gradle.sh13-115
Step 1 — Generate BuildConfig.java (server/build_without_gradle.sh39-46)
The script uses a heredoc to write a BuildConfig.java file into $GEN_DIR/com/genymobile/scrcpy/. This replaces what Gradle's buildConfig = true feature would generate automatically. The constants DEBUG (false) and VERSION_NAME ("3.3.4") are embedded as literals.
Step 2 — AIDL Compilation (server/build_without_gradle.sh48-53)
Two AIDL files are compiled to Java stubs using the aidl binary from $BUILD_TOOLS_DIR:
| AIDL File | Extra Flag |
|---|---|
android/content/IOnPrimaryClipChangedListener.aidl | None |
android/view/IDisplayWindowListener.aidl | -p "$ANDROID_AIDL" (framework AIDL preprocessed) |
Output stubs are placed in $GEN_DIR.
Step 3 — Fake Sources (server/build_without_gradle.sh55-58)
The FAKE_SRC array picks up files matching android/content/*java from the AIDL source directory. These expose hidden Android types to the compiler without requiring a full Android system image. They stand in for types not present in the public android.jar.
Step 4 — javac Compilation (server/build_without_gradle.sh77-84)
The Java source tree is compiled:
-bootclasspath "$ANDROID_JAR" — compiles against the Android platform JAR rather than the desktop JDK runtime.-cp "$LAMBDA_JAR:$GEN_DIR" — adds lambda desugaring stubs (core-lambda-stubs.jar) and the generated AIDL stubs.-source 1.8 -target 1.8 — targets Java 8 bytecode.Source packages compiled:
com/genymobile/scrcpy/*.java
com/genymobile/scrcpy/audio/*.java
com/genymobile/scrcpy/control/*.java
com/genymobile/scrcpy/device/*.java
com/genymobile/scrcpy/opengl/*.java
com/genymobile/scrcpy/util/*.java
com/genymobile/scrcpy/video/*.java
com/genymobile/scrcpy/wrappers/*.java
Step 5 — DEX Conversion (server/build_without_gradle.sh86-111)
The DEX tool selected depends on ANDROID_PLATFORM:
| Platform | Tool | Output |
|---|---|---|
| < 31 | dx --dex | classes.dex → archived into JAR as scrcpy-server |
| ≥ 31 | d8 | classes.zip → renamed to scrcpy-server |
In both cases, the final file named scrcpy-server is a ZIP-format archive containing classes.dex.
Sources: server/build_without_gradle.sh86-115
Server Source Layout → Build Artifact
Sources: server/build_without_gradle.sh38-113 server/build.gradle22-26
The server accesses private Android APIs that are not part of the public SDK. To allow compilation against android.jar (which does not expose hidden APIs), the build includes fake source stubs.
In the Gradle build, this is handled by the android.content stubs checked into server/src/main/aidl/android/content/. In the manual script, FAKE_SRC at server/build_without_gradle.sh56-58 expands android/content/*java and passes those files directly to javac alongside the main sources. These stubs define just enough of the hidden type signatures for javac to accept the imports — the real implementations exist on the Android system and are accessed at runtime via reflection. See Android Framework Wrappers for details on how those wrappers use these types.
Sources: server/build_without_gradle.sh55-84
The settings.gradle (not listed but implied by Gradle project structure) and build.gradle at the project root coordinate the plugin versions. The server/build.gradle itself has no external library dependencies beyond the Android framework and a JUnit test dependency:
testImplementation 'junit:junit:4.13.2'
No third-party runtime libraries are bundled into the server JAR. All functionality depends on Android system services accessed via the wrappers described in Android Framework Wrappers.
Sources: server/build.gradle29-33
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.