Interested in helping to convert the CoffeeScript codebase to plain JavaScript? Help us!

adbkit is a pure Node.js client for the Android Debug Bridge server. It can be used either as a library in your own application, or simply as a convenient utility for playing with your device.

Most of the adb command line tool's functionality is supported (including pushing/pulling files, installing APKs and processing logs), with some added functionality such as being able to generate touch/key events and take screenshots. Some shims are provided for older devices, but we have not and will not test anything below Android 2.3.

Internally, we use this library to drive a multitude of Android devices from a variety of manufacturers, so we can say with a fairly high degree of confidence that it will most likely work with your device(s), too.

Please note that although it may happen at some point, this project is NOT an implementation of the ADB server. The target host (where the devices are connected) must still have ADB installed and either already running (e.g. via adb start-server) or available in $PATH. An attempt will be made to start the server locally via the aforementioned command if the initial connection fails. This is the only case where we fall back to the adb binary.

When targeting a remote host, starting the server is entirely your responsibility.

Alternatively, you may want to consider using the Chrome ADB extension, as it includes the ADB server and can be started/stopped quite easily.

We use debug, and our debug namespace is adb. Some of the dependencies may provide debug output of their own. To see the debug output, set the DEBUG environment variable. For example, run your program with DEBUG=adb:* node app.js.

Note that even though the module is written in CoffeeScript, only the compiled JavaScript is published to NPM, which means that it can easily be used with pure JavaScript codebases, too.

key The key as a forge.pki public key. You may need node-forge for complicated operations. Additionally the following properties are present:

fingerprint The key fingerprint, like it would display on a device. Note that this is different than the one you'd get from forge.ssh.getPublicKeyFingerprint(key), because the device fingerprint is based on the original format.

Note: be careful with using client.listDevices() together with client.tcpip() and other similar methods that modify the connection with ADB. You might have the same device twice in your device list (i.e. one device connected via both USB and TCP), which can cause havoc if run simultaneously.

Disconnects from the given device, which should have been connected via client.connect() or just adb connect <host>:<port>.

host The target host. Can also contain the port, in which case the port argument is not used and can be skipped. In other words you can just put the id you got from client.connect() here and it will be fine.

port Optional. The target port. Defaults to 5555.

callback(err, id) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

id The disconnected device ID. Will no longer be usable as a serial in other commands until you've connected again.

Forwards socket connections from the ADB server host (local) to the device (remote). This is analogous to adb forward <local> <remote>. It's important to note that if you are connected to a remote ADB server, the forward will be created on that host.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

local A string representing the local endpoint on the ADB host. At time of writing, can be one of:

tcp:<port>

localabstract:<unix domain socket name>

localreserved:<unix domain socket name>

localfilesystem:<unix domain socket name>

dev:<character device name>

remote A string representing the remote endpoint on the device. At time of writing, can be one of:

Fetches the current raw framebuffer (i.e. what is visible on the screen) from the device, and optionally converts it into something more usable by using GraphicsMagick's gm command, which must be available in $PATH if conversion is desired. Note that we don't bother supporting really old framebuffer formats such as RGB_565. If for some mysterious reason you happen to run into a >=2.3 device that uses RGB_565, let us know.

Note that high-resolution devices can have quite massive framebuffers. For example, a device with a resolution of 1920x1080 and 32 bit colors would have a roughly 8MB (1920*1080*4 byte) RGBA framebuffer. Empirical tests point to about 5MB/s bandwidth limit for the ADB USB connection, which means that it can take ~1.6 seconds for the raw data to arrive, or even more if the USB connection is already congested. Using a conversion will further slow down completion.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

format The desired output format. Any output format supported by GraphicsMagick (such as 'png') is supported. Defaults to 'raw' for raw framebuffer data.

callback(err, framebuffer) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

framebuffer The possibly converted framebuffer stream. The stream also has a meta property with the following values:

version The framebuffer version. Useful for patching possible backwards-compatibility issues.

bpp Bits per pixel (i.e. color depth).

size The raw byte size of the framebuffer.

width The horizontal resolution of the framebuffer. This SHOULD always be the same as screen width. We have not encountered any device with incorrect framebuffer metadata, but according to rumors there might be some.

height The vertical resolution of the framebuffer. This SHOULD always be the same as screen height.

red_offset The bit offset of the red color in a pixel.

red_length The bit length of the red color in a pixel.

blue_offset The bit offset of the blue color in a pixel.

blue_length The bit length of the blue color in a pixel.

green_offset The bit offset of the green color in a pixel.

green_length The bit length of the green color in a pixel.

alpha_offset The bit offset of alpha in a pixel.

alpha_length The bit length of alpha in a pixel. 0 when not available.

format The framebuffer format for convenience. This can be one of 'bgr', 'bgra', 'rgb', 'rgba'.

Retrieves the features of the device identified by the given serial number. This is analogous to adb shell pm list features. Useful for checking whether hardware features such as NFC are available (you'd check for 'android.hardware.nfc').

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

callback(err, features) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

features An object of device features. Each key corresponds to a device feature, with the value being either true for a boolean feature, or the feature value as a string (e.g. '0x20000' for reqGlEsVersion).

Gets the serial number of the device identified by the given serial number. With our API this doesn't really make much sense, but it has been implemented for completeness. FYI: in the raw ADB protocol you can specify a device in other ways, too.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

Installs an APK file which must already be located on the device file system, and replaces any previously installed version. Useful if you've previously pushed the file to the device for some reason (perhaps to have direct access to client.push()'s transfer stats). This is roughly analogous to adb shell pm install -r <apk> followed by adb shell rm -f <apk>.

Note that if the call seems to stall, you may have to accept a dialog on the phone first.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

apk The path to the APK file on the device. The file will be removed when the command completes.

devices An array of device objects. The device objects are plain JavaScript objects with two properties: id and type.

id The ID of the device. For real devices, this is usually the USB identifier.

type The device type. Values include 'emulator' for emulators, 'device' for devices, and 'offline' for offline devices. 'offline' can occur for example during boot, in low-battery conditions or when the ADB connection has not yet been approved on the device.

Calls the logcat utility on the device and hands off the connection to adbkit-logcat, a pure Node.js Logcat client. This is analogous to adb logcat -B, but the event stream will be parsed for you and a separate event will be emitted for every log entry, allowing for easy processing.

Starts the built-in monkey utility on the device, connects to it using client.openTcp() and hands the connection to adbkit-monkey, a pure Node.js Monkey client. This allows you to create touch and key events, among other things.

Tracks /proc/stat and emits useful information, such as CPU load. A single sync service instance is used to download the /proc/stat file for processing. While doing this does consume some resources, it is very light and should not be a problem.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

callback(err, stats) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

stats The /proc/stat tracker, which is an EventEmitter. Call stat.end() to stop tracking. The following events are available:

load(loads) Emitted when a CPU load calculation is available.

loads CPU loads of online CPUs. Each key is a CPU id (e.g. 'cpu0', 'cpu1') and the value an object with the following properties:

Opens a direct TCP connection to a port on the device, without any port forwarding required.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

port The port number to connect to.

host Optional. The host to connect to. Allegedly this is supposed to establish a connection to the given host from the device, but we have not been able to get it to work at all. Skip the host and everything works great.

callback(err, conn) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

conn The TCP connection (i.e. net.Socket). Read and write as you please. Call conn.end() to end the connection.

A convenience shortcut for sync.pull(), mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

A convenience shortcut for sync.push(), mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

A convenience shortcut for sync.readdir(), mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

path See sync.readdir() for details.

callback(err, files) Optional. Use this or the returned Promise. See sync.readdir() for details.

Reboots the device. Similar to adb reboot. Note that the method resolves when ADB reports that the device has been rebooted (i.e. the reboot command was successful), not when the device becomes available again.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

Reverses socket connections from the device (remote) to the ADB server host (local). This is analogous to adb reverse <remote> <local>. It's important to note that if you are connected to a remote ADB server, the reverse will be created on that host.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

remote A string representing the remote endpoint on the device. At time of writing, can be one of:

tcp:<port>

localabstract:<unix domain socket name>

localreserved:<unix domain socket name>

localfilesystem:<unix domain socket name>

local A string representing the local endpoint on the ADB host. At time of writing, can be any value accepted by the remote argument.

Takes a screenshot in PNG format using the built-in screencap utility. This is analogous to adb shell screencap -p. Sadly, the utility is not available on most Android <=2.3 devices, but a silent fallback to the client.framebuffer() command in PNG mode is attempted, so you should have its dependencies installed just in case.

Generating the PNG on the device naturally requires considerably more processing time on that side. However, as the data transferred over USB easily decreases by ~95%, and no conversion being required on the host, this method is usually several times faster than using the framebuffer. Naturally, this benefit does not apply if we're forced to fall back to the framebuffer.

For convenience purposes, if the screencap command fails (e.g. because it doesn't exist on older Androids), we fall back to client.framebuffer(serial, 'png'), which is slower and has additional installation requirements.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

options The activity configuration. The following options are available:

debug Set to true to enable debugging.

wait Set to true to wait for the activity to launch.

user The user to run as. Not set by default. If the option is unsupported by the device, an attempt will be made to run the same command again without the user option.

action The action.

data The data URI, if any.

mimeType The mime type, if any.

category The category. For multiple categories, pass an Array.

component The component.

flags Numeric flags.

extras Any extra data.

When an Array, each item must be an Object the following properties:

key The key name.

type The type, which can be one of 'string', 'null', 'bool', 'int', 'long', 'float', 'uri', 'component'.

value The value. Optional and unused if type is 'null'. If an Array, type is automatically set to be an array of <type>.

When an Object, each key is treated as the key name. Simple values like null, String, Boolean and Number are type-mapped automatically (Number maps to 'int') and can be used as-is. For more complex types, like arrays and URIs, set the value to be an Object like in the Array syntax (see above), but leave out the key property.

A convenience shortcut for sync.stat(), mainly for one-off use cases. The connection cannot be reused, resulting in poorer performance over multiple calls. However, the Sync client will be closed automatically for you, so that's one less thing to worry about.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

path See sync.stat() for details.

callback(err, stats) Optional. Use this or the returned Promise. See sync.stat() for details.

Establishes a new Sync connection that can be used to push and pull files. This method provides the most freedom and the best performance for repeated use, but can be a bit cumbersome to use. For simple use cases, consider using client.stat(), client.push() and client.pull().

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

callback(err, sync) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

sync The Sync client. See below for details. Call sync.end() when done.

Puts the device's ADB daemon into tcp mode, allowing you to use adb connect or client.connect() to connect to it. Note that the device will still be visible to ADB as a regular USB-connected device until you unplug it. Same as adb tcpip <port>.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

port Optional. The port the device should listen on. Defaults to 5555.

Gets a device tracker. Events will be emitted when devices are added, removed, or their type changes (i.e. to/from offline). Note that the same events will be emitted for the initially connected devices also, so that you don't need to use both client.listDevices() and client.trackDevices().

Note that as the tracker will keep a connection open, you must call tracker.end() if you wish to stop tracking devices.

callback(err, tracker) Optional. Use this or the returned Promise.

errnull when successful, Error otherwise.

tracker The device tracker, which is an EventEmitter. The following events are available:

add(device) Emitted when a new device is connected, once per device. See client.listDevices() for details on the device object.

remove(device) Emitted when a device is unplugged, once per device. This does not include offline devices, those devices are connected but unavailable to ADB. See client.listDevices() for details on the device object.

change(device) Emitted when the type property of a device changes, once per device. The current value of type is the new value. This event usually occurs the type changes from 'device' to 'offline' or the other way around. See client.listDevices() for details on the device object and the 'offline' type.

changeSet(changes) Emitted once for all changes reported by ADB in a single run. Multiple changes can occur when, for example, a USB hub is connected/unplugged and the device list changes quickly. If you wish to process all changes at once, use this event instead of the once-per-device ones. Keep in mind that the other events will still be emitted, though.

changes An object with the following properties always present:

added An array of added device objects, each one as in the add event. Empty if none.

removed An array of removed device objects, each one as in the remove event. Empty if none.

changed An array of changed device objects, each one as in the change event. Empty if none.

Waits until ADB can see the device. Note that you must know the serial in advance. Other than that, works like adb -s serial wait-for-device. If you're planning on reacting to random devices being plugged in and out, consider using client.trackDevices() instead.

serial The serial number of the device. Corresponds to the device ID in client.listDevices().

callback(err, id) Optional. Use this or the returned Promise.

errnull if the device has completed booting, Error otherwise (can occur if the connection dies while checking).

Cancels the transfer by ending both the stream that is being pushed and the sync connection. This will most likely end up creating a broken file on your device. Use at your own risk. Also note that you must create a new sync connection if you wish to continue using the sync service.

Cancels the transfer by ending the connection. Can be useful for reading endless streams of data, such as /dev/urandom or /dev/zero, perhaps for benchmarking use. Note that you must create a new sync connection if you wish to continue using the sync service.

Previously, we made extensive use of callbacks in almost every feature. While this normally works okay, ADB connections can be quite fickle, and it was starting to become difficult to handle every possible error. For example, we'd often fail to properly clean up after ourselves when a connection suddenly died in an unexpected place, causing memory and resource leaks.

In version 2, we've replaced nearly all callbacks with Promises (using Bluebird), allowing for much more reliable error propagation and resource cleanup (thanks to .finally()). Additionally, many commands can now be cancelled on the fly, and although unimplemented at this point, we'll also be able to report progress on long-running commands without any changes to the API.

Unfortunately, some API changes were required for this change. client.framebuffer()'s callback, for example, previously accepted more than one argument, which doesn't translate into Promises so well. Thankfully, it made sense to combine the arguments anyway, and we were able to do it quite cleanly.

Furthermore, most API methods were returning the current instance for chaining purposes. While perhaps useful in some contexts, most of the time it probably didn't quite do what users expected, as chained calls were run in parallel rather than in serial fashion. Now every applicable API method returns a Promise, which is an incompatible but welcome change. This will also allow you to hook into yield and coroutines in Node 0.12.

However, all methods still accept (and will accept in the future) callbacks for those who prefer them.

Test coverage was also massively improved, although we've still got ways to go.