Skip to main content
Version: 2.1.0

Push server to device

The server file needs to be copied to the device and executed on it. It will listen on a UNIX domain socket and wait for connections from the client.

The default path of the server file on device is /data/local/tmp/scrcpy-server.jar. Before version 2.3, the path of Scrcpy server binary is hard-coded in the server itself. So you must push it to this exact path, otherwise the clean up steps won't delete the server file.

Equivalent ADB command
adb push scrcpy-server.jar /data/local/tmp/scrcpy-server.jar

With @yume-chan/scrcpy

@yume-chan/scrcpy only provides APIs to serialize and deserialize Scrcpy protocol messages. It doesn't provide any APIs to interact with the device.

With @yume-chan/adb-scrcpy

@yume-chan/adb-scrcpy package provides a pushServer function as a shortcut for the Tango AdbSync#write call.

import type { Adb } from "@yume-chan/adb";
import type { ReadableStream, MaybeConsumable } from "@yume-chan/stream-extra";

declare class AdbScrcpyClient {
static async pushServer(
adb: Adb,
file: ReadableStream<MaybeConsumable<Uint8Array>>,
filename?: string,
);
}
ParameterRequired/Default valueDescription
adbRequiredAn Adb instance to run ADB commands.
fileRequiredA readable stream containing the server file.
filenameimport("@yume-chan/scrcpy").DefaultServerPathThe path on device to push the server file to.

By default, it pushes to /data/local/tmp/scrcpy-server.jar. This path is also exported from @yume-chan/scrcpy package as DefaultServerPath.

If a custom path is specified, the same value must be used when starting the server.

Examples

import type { Adb } from "@yume-chan/adb";
import { AdbScrcpyClient } from "@yume-chan/adb-scrcpy";
import { ReadableStream } from "@yume-chan/stream-extra";

declare const adb: Adb;
declare const server: ArrayBuffer;

await AdbScrcpyClient.pushServer(
adb,
new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array(server));
controller.close();
},
}),
);

Push to a custom path:

import type { Adb } from "@yume-chan/adb";
import { AdbScrcpyClient } from "@yume-chan/adb-scrcpy";
import { ReadableStream } from "@yume-chan/stream-extra";

declare const adb: Adb;
declare const server: ArrayBuffer;

await AdbScrcpyClient.pushServer(
adb,
new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array(server));
controller.close();
},
}),
"/data/local/tmp/scrcpy-server-3.2.jar",
);

Using fetch

When downloading the server binary using fetch, Response.body is a ReadableStream<Uint8Array> that can be directly piped to pushServer.

In theory, this is also faster, because the downloading and pushing are run in parallel. Although in practice, the server binary is too small to make a difference.

import type { Adb } from "@yume-chan/adb";
import type { ReadableStream } from "@yume-chan/stream-extra";

declare const adb: Adb;
declare const url: URL;

const response = await fetch(url);

await AdbScrcpyClient.pushServer(
adb,
// The `ReadableStream` type in TypeScript `lib.dom.d.ts` is not compatible with Tango's Web Streams API typings
response.body as never as ReadableStream<Uint8Array>,
);

With Tango

The above code is a shortcut for the following code:

import type { Adb } from "@yume-chan/adb";
import { ReadableStream } from "@yume-chan/stream-extra";

declare const adb: Adb;
declare const server: ArrayBuffer;

const sync = await adb.sync();
try {
await sync.write({
filename: "/data/local/tmp/scrcpy-server.jar",
file: new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array(server));
controller.close();
},
}),
});
} finally {
await sync.dispose();
}

Or using fetch:

import type { Adb } from "@yume-chan/adb";
import type { ReadableStream } from "@yume-chan/stream-extra";

declare const adb: Adb;
declare const url: URL;

const response = await fetch(url);

const sync = await adb.sync();
try {
await sync.write({
filename: "/data/local/tmp/scrcpy-server.jar",
// The `ReadableStream` type in TypeScript `lib.dom.d.ts` is not compatible with Tango's Web Streams API typings
file: response.body as never as ReadableStream<Uint8Array>,
});
} finally {
await sync.dispose();
}