diff --git a/.vscode/settings.json b/.vscode/settings.json
index 25d94e28..511bc772 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,6 +2,7 @@
"cSpell.words": [
"ADB's",
"adbd",
+ "addrs",
"allowlist",
"arraybuffer",
"autorun",
diff --git a/README.md b/README.md
index ae6776a3..a8824be1 100644
--- a/README.md
+++ b/README.md
@@ -24,10 +24,10 @@ In this mode, this library talks to a Google ADB server, which is either running
## Compatibility
-| Connection | Chromium-based Browsers | Firefox | Node.js |
-| ----------------------------------------- | ------------------------------ | --------- | ----------------------------- |
-| USB cable | Supported using [WebUSB] API | No | Supported using `usb` package |
-| Wireless through [WebSocket] 1 | Supported | Supported | Possible using `ws` package |
+| Connection | Chromium-based Browsers | Firefox | Node.js |
+| ----------------------------------------- | -------------------------------- | --------- | ----------------------------- |
+| USB cable | Supported using [WebUSB] API | No | Supported using `usb` package |
+| Wireless through [WebSocket] 1 | Supported | Supported | Possible using `ws` package |
| Wireless through TCP | Waiting for [Direct Sockets] API | No | Possible using `net` module |
[webusb]: https://wicg.github.io/webusb/
diff --git a/apps/demo/src/pages/tcpip.tsx b/apps/demo/src/pages/tcpip.tsx
index 48e46258..927c2666 100644
--- a/apps/demo/src/pages/tcpip.tsx
+++ b/apps/demo/src/pages/tcpip.tsx
@@ -77,30 +77,19 @@ class TcpIpState {
return;
}
- const serviceListenAddresses = await GLOBAL_STATE.adb.getProp(
- "service.adb.listen_addrs"
- );
- const servicePort = await GLOBAL_STATE.adb.getProp(
- "service.adb.tcp.port"
- );
- const persistPort = await GLOBAL_STATE.adb.getProp(
- "persist.adb.tcp.port"
- );
+ const { serviceListenAddresses, servicePort, persistPort } =
+ await GLOBAL_STATE.adb.tcpip.getListenAddresses();
if (signal.aborted) {
return;
}
runInAction(() => {
- this.serviceListenAddresses =
- serviceListenAddresses !== ""
- ? serviceListenAddresses.split(",")
- : undefined;
+ this.serviceListenAddresses = serviceListenAddresses;
if (servicePort) {
- this.servicePortEnabled =
- !serviceListenAddresses && servicePort !== "0";
- this.servicePort = servicePort;
+ this.servicePortEnabled = !serviceListenAddresses;
+ this.servicePort = servicePort.toString();
} else {
this.servicePortEnabled = false;
this.servicePort = "5555";
@@ -109,7 +98,7 @@ class TcpIpState {
if (persistPort) {
this.persistPortEnabled =
!serviceListenAddresses && !servicePort;
- this.persistPort = persistPort;
+ this.persistPort = persistPort.toString();
} else {
this.persistPortEnabled = false;
this.persistPort = undefined;
@@ -124,7 +113,7 @@ class TcpIpState {
if (state.servicePortEnabled) {
await GLOBAL_STATE.adb.tcpip.setPort(
- Number.parseInt(state.servicePort, 10)
+ Number.parseInt(state.servicePort, 10),
);
} else {
await GLOBAL_STATE.adb.tcpip.disable();
@@ -153,7 +142,7 @@ const TcpIp: NextPage = () => {
state.servicePortEnabled = !!value;
});
},
- []
+ [],
);
const handleServicePortChange = useCallback(
@@ -163,7 +152,7 @@ const TcpIp: NextPage = () => {
}
runInAction(() => (state.servicePort = value));
},
- []
+ [],
);
return (
diff --git a/common/changes/@yume-chan/adb/main_2023-08-25-16-30.json b/common/changes/@yume-chan/adb/main_2023-08-25-16-30.json
new file mode 100644
index 00000000..92086ee0
--- /dev/null
+++ b/common/changes/@yume-chan/adb/main_2023-08-25-16-30.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@yume-chan/adb",
+ "comment": "Add `getListenAddresses` method to `AdbTcpIpCommand` class for retrieving current ADB over WiFi state",
+ "type": "none"
+ }
+ ],
+ "packageName": "@yume-chan/adb"
+}
\ No newline at end of file
diff --git a/libraries/adb/src/commands/tcpip.ts b/libraries/adb/src/commands/tcpip.ts
index e91def10..387480bb 100644
--- a/libraries/adb/src/commands/tcpip.ts
+++ b/libraries/adb/src/commands/tcpip.ts
@@ -1,6 +1,47 @@
import { AdbCommandBase } from "./base.js";
+/**
+ * ADB daemon checks for the following properties in the order of
+ *
+ * * `serviceListenAddresses` (`service.adb.listen_addrs`)
+ * * `servicePort` (`service.adb.tcp.port`)
+ * * `persistPort` (`persist.adb.tcp.port`)
+ *
+ * Once it finds a non-empty value, it will use it and ignore the rest.
+ *
+ * `serviceListenAddresses` and `persistPort` are fixed at build time,
+ * only `servicePort` can be changed using `setPort` and `disable`.
+ * This means if either `serviceListenAddresses` or `persistPort` is non-empty,
+ * ADB over WiFi is always enabled.
+ */
+export interface AdbTcpIpListenAddresses {
+ serviceListenAddresses: string[];
+ servicePort: number | undefined;
+ persistPort: number | undefined;
+}
+
export class AdbTcpIpCommand extends AdbCommandBase {
+ #parsePort(value: string): number | undefined {
+ if (!value || value === "0") {
+ return undefined;
+ }
+ return Number.parseInt(value, 10);
+ }
+
+ async getListenAddresses(): Promise {
+ const serviceListenAddresses = await this.adb.getProp(
+ "service.adb.listen_addrs",
+ );
+ const servicePort = await this.adb.getProp("service.adb.tcp.port");
+ const persistPort = await this.adb.getProp("persist.adb.tcp.port");
+
+ return {
+ serviceListenAddresses: serviceListenAddresses.split(","),
+ servicePort: this.#parsePort(servicePort),
+ persistPort: this.#parsePort(persistPort),
+ };
+ }
+
async setPort(port: number): Promise {
if (port <= 0) {
throw new Error(`Invalid port ${port}`);