Handshake and authenticate
Authenticate with device
Once a connection and a credential store is ready, use adbDaemonAuthenticate function to initiate the handshake and authenticate with the device.
type AdbDaemonConnection = ReadableWritablePair<
AdbPacketData,
Consumable<AdbPacketInit>
>;
interface AdbDaemonAuthenticateOptions {
/**
* The serial number of the device to connect to.
*/
serial: string;
/**
* The ADB daemon connection to use for communication.
*/
connection: AdbDaemonConnection;
/**
* The list of features to send to the device during handshake.
* @default AdbDeviceFeatures
*/
features?: readonly AdbFeature[];
/**
* The number of bytes the device can send before receiving an ack packet.
* Setting this to 0 or a negative number will disable Delayed Ack.
* @default ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE
*/
initialDelayedAckBytes?: number;
/**
* Whether to preserve the connection when the transport is closed.
* @default false
*/
preserveConnection?: boolean;
/**
* Time limit for reading from the connection, in milliseconds.
* @default undefined
*/
readTimeLimit?: number;
} & (
| AdbDaemonDefaultAuthProcessorInit // Shortcut to use default authentication processor with credential store
| { processor: AdbDaemonAuthProcessor } // Use a custom authentication processor
);
/**
* Authenticates an `AdbDaemonConnection` using an `AdbDaemonAuthProcessor`.
*/
declare function adbDaemonAuthenticate(
options: AdbDaemonAuthenticateOptions
): Promise<AdbDaemonTransport>;
serial
The serial field is not used by Tango, it helps you to identify the device associated with the transport. You can use any string to represent the device.
connection
A pair of ReadableStream<AdbPacketData> and WritableStream<Consumable<AdbPacketInit>> is used to send and receive ADB packets. You can use any stream implementation that conforms to the interface.
features
An optional list of AdbFeature to send to the device in handshake. ADB Features are flags that can be used to enable or disable certain features in the ADB protocol. The default value contains all features supported by Tango.
initialDelayedAckBytes
On Android 14 and newer, the Delayed Acknowledgement feature is added to improve performance, especially for high-latency connections like ADB over Wi-Fi. For more details on how this feature works internally, see Delayed Acknowledgment in ADB.
This optional field specifies The number of bytes the device can send before receiving an ack packet.
Setting this parameter to 0 or a negative number will disable Delayed Ack.
preserveConnection
When set to true, the transport will not close the connection when the close method is called.
This is useful when you want to reconnect to the device later without re-authenticating.
The default value is false.
If the authentication process fails, the connection will always be kept open, regardless of this option.
readTimeLimit
When set, the transport will throw an error when one of the socket readable stalls for this amount of milliseconds.
This option is helpful to detect bugs in the client code that causes child processes to hang or future commands not executed.
When set to undefined, the transport will not enforce a time limit.
The default value is undefined.
Authentication Options
The adbDaemonAuthenticate function requires exactly one of two authentication approaches, specified through mutually exclusive options:
- Pass
credentialManageras part ofAdbDaemonDefaultAuthProcessorInit, which creates a default authentication processor using the provided credential manager. This is the standard authentication flow for most use cases. - Pass a custom
processoroption with your own implementation ofAdbDaemonAuthProcessor. This allows for completely custom authentication logic.
AdbDaemonDefaultAuthProcessorInit
When using the default authentication flow, you can provide these options:
interface AdbDaemonDefaultAuthProcessorInit {
/**
* An AdbCredentialManager implementation to store and retrieve private keys.
* Used to provide authentication keys during the handshake.
*/
credentialManager: AdbCredentialManager;
/**
* An optional callback that gets invoked when a key fails to load from the credential manager.
*/
onKeyLoadError?: ((error: Error) => void) | undefined;
/**
* An optional callback that gets invoked when signature authentication is attempted with a key.
*/
onSignatureAuthentication?: ((key: AdbKeyInfo) => void) | undefined;
/**
* An optional callback that gets invoked when a signature is rejected by the device.
*/
onSignatureRejected?: ((key: AdbKeyInfo) => void) | undefined;
/**
* An optional callback that gets invoked when public key authentication is initiated.
*/
onPublicKeyAuthentication?: ((key: AdbKeyInfo) => void) | undefined;
}
These fields are passed directly into adbDaemonAuthenticate, not as a separate object. For example, { serial, connection, credentialManager, onKeyLoadError } instead of { serial, connection, authProcessor: { credentialManager, onKeyLoadError } }.
credentialManager
An AdbCredentialManager implementation is used to store and retrieve the private key. You can use any store that conforms to the interface.
Passing credentialManager is a shortcut that creates a default authentication processor internally. This is the common case for standard authentication flows.
onKeyLoadError
An optional callback that gets invoked when a key fails to load from the credential manager. This allows for handling errors during key iteration without stopping the entire authentication process.
onSignatureAuthentication
An optional callback that gets invoked when signature authentication is attempted with a key. Provides information about the key being used.
onSignatureRejected
An optional callback that gets invoked when a signature is rejected by the device. This indicates that the key hasn't been trusted by the user yet.
onPublicKeyAuthentication
An optional callback that gets invoked when public key authentication is initiated. This typically happens when the device doesn't trust any of the available keys.
Example
When using the default authentication flow with a credential manager:
- JavaScript
- TypeScript
import { adbDaemonAuthenticate } from "@yume-chan/adb";
const transport = await adbDaemonAuthenticate({
serial: device.serial,
connection,
credentialManager: CredentialManager,
});
import type { AdbPacketData, AdbPacketInit } from "@yume-chan/adb";
import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
import { adbDaemonAuthenticate, AdbWebCryptoCredentialManager } from "@yume-chan/adb";
import { AdbDaemonWebUsbDevice } from "@yume-chan/adb-daemon-webusb";
import { TangoLocalStorage } from "@yume-chan/adb-credential-web";
declare const device: AdbDaemonWebUsbDevice;
declare const connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>;
declare const CredentialManager: AdbWebCryptoCredentialManager;
const transport: AdbDaemonTransport = await adbDaemonAuthenticate({
serial: device.serial,
connection,
credentialManager: CredentialManager,
});
If the private key is not yet trusted by the device, a dialog will be shown on device screen to let users confirm the connection.
processor
A custom AdbDaemonAuthProcessor implementation to handle the authentication process. When provided, this overrides the default authentication processor that would be created from credentialManager.
Use this option when you need custom authentication logic that differs from the standard flow.
Example
When using a custom authentication processor:
- JavaScript
- TypeScript
import { adbDaemonAuthenticate } from "@yume-chan/adb";
const transport = await adbDaemonAuthenticate({
serial: device.serial,
connection,
processor: customAuthProcessor,
});
import type { AdbPacketData, AdbPacketInit } from "@yume-chan/adb";
import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
import { adbDaemonAuthenticate, AdbDaemonAuthProcessor } from "@yume-chan/adb";
import { AdbDaemonWebUsbDevice } from "@yume-chan/adb-daemon-webusb";
declare const device: AdbDaemonWebUsbDevice;
declare const connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>;
declare const customAuthProcessor: AdbDaemonAuthProcessor;
const transport: AdbDaemonTransport = await adbDaemonAuthenticate({
serial: device.serial,
connection,
processor: customAuthProcessor,
});
This approach allows for completely custom authentication logic when the default flow is insufficient.
Create an Adb instance
The transport object only contains the lower-level logic to communicate with devices, the Adb class provides a higher-level abstraction over ADB protocol and ADB commands.
This step only initialize some internal states, but does not actually send any packets to the device.
- JavaScript
- TypeScript
import { Adb } from "@yume-chan/adb";
const adb = new Adb(transport);
import { Adb } from "@yume-chan/adb";
const adb: Adb = new Adb(transport);
See API section for all supported ADB commands.