NAME

Net::ADB - Client for ADB (Android Debug Bridge) Server

SYNOPSIS

use Net::ADB;

my $adb = Net::ADB->new;

say $adb->version;    # 41

# List the connected devices
for my $device ($adb->devices) {
    say "$device->{serial} $device->{state}";
}

# Run a command on the only connected device
my $res = $adb->shell_v2(command => 'getprop ro.product.model');

say $res->stdout;       # Example Phone
say $res->exit_code;    # 0

# Select a device by serial, USB or TCP/IP
$res = $adb->shell_v2(serial => 'emulator-5554', command => 'uptime');
$res = $adb->shell_v2(usb    => 1,               command => 'uptime');

# Connect a device over TCP/IP (Wi-Fi)
$adb->connect(host => '192.168.0.10', port => 5555);

# Forward a local port to the device
my $port = $adb->forward(usb => 1, local => 'tcp:0', remote => 'tcp:8080');

# Device-bound wrapper
my $device = $adb->device(serial => 'emulator-5554');

say $device->info->{model};

DESCRIPTION

Net::ADB is a pure-Perl client for the ADB (Android Debug Bridge) server.

The ADB server is the background process started by the adb command line tool (adb start-server), listening by default on 127.0.0.1:5037. It keeps track of the connected Android devices (USB, TCP/IP, emulators) and relays the requests of its clients to the adbd daemon running on each device.

Net::ADB speaks the ADB server protocol directly over TCP, without running the adb executable, so the server must already be running. Each method opens a new connection to the server.

For more information about the ADB server protocol and services follow the online documentation:

https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/master/docs/dev/services.md

CONSTRUCTOR

new

# Default ADB host & port (127.0.0.1:5037)
my $adb = Net::ADB->new;

# Specify ADB host, port and timeout
my $adb = Net::ADB->new(host => '127.0.0.1', port => 5037, timeout => 10);

Create a new Net::ADB instance.

Allowed parameters:

  • host, ADB server host (default: 127.0.0.1).

  • port, ADB server port (default: 5037).

  • timeout, timeout in seconds for connecting to the server and for each read (default: 10).

DEVICE SELECTION

Methods that act on a device accept at most one of these parameters:

  • serial, the device with the given serial, as listed by "devices" (e.g. emulator-5554, 192.168.0.10:5555). Same as adb -s.

  • usb, the only device connected via USB. Same as adb -d.

  • tcp, the only device connected via TCP/IP (adb connect, wireless debugging, emulators). Same as adb -e.

$adb->state(serial => 'emulator-5554');
$adb->state(usb => 1);
$adb->state(tcp => 1);

Without any of them, the only connected device is used. If the selection matches no device, or more than one, the method croaks with the server message (e.g. more than one device/emulator).

With several devices of the same kind (e.g. two phones via USB), usb and tcp croak as well: use serial. "devices" lists the serials, and USB devices have the usb attribute:

for my $d ($adb->devices) {
    next unless $d->{state} eq 'device';

    my $via = exists $d->{usb} ? 'USB' : 'TCP/IP';
    say "$d->{serial} ($via): ", $adb->device(serial => $d->{serial})->info->{model};
}

The serial identifies a connection, not a phone: the same phone connected both via USB and Wi-Fi is listed twice, with two different serials. To group the connections by phone, compare a device property such as ro.serialno (see "info" in Net::ADB::Device):

my %phones;

for my $d (grep { $_->{state} eq 'device' } $adb->devices) {
    my $id = $adb->device(serial => $d->{serial})->info->{serial};
    push @{$phones{$id}}, $d->{serial};
}

# { 'EX0123456789' => ['EX0123456789', '192.168.0.10:5555'] }

METHODS

Server

version

my $version = $adb->version;    # 41

Return the version of the ADB server as an integer: 41 for the server reported by adb version as "1.0.41".

Same as adb version, host:version service.

devices

my @devices = $adb->devices;

for my $device (@devices) {
    say "$device->{serial} $device->{state}";
}

my $devices = $adb->devices;    # array reference

Return the list of devices known to the server (an array reference in scalar context), one hash reference per device.

Each device has serial and state (device, offline, unauthorized, ...) plus the attributes reported by the server, such as product, model, device, transport_id and, for USB devices, usb.

{
    serial       => '192.168.0.10:5555',
    state        => 'device',
    product      => 'example',
    model        => 'Example_Phone',
    device       => 'example',
    transport_id => '3'
}

Same as adb devices -l, host:devices-l service.

kill

$adb->kill;

Stop the ADB server and return 1. This module does not restart it: the next adb command (or adb start-server) does.

Same as adb kill-server, host:kill service.

Device

device

my $device = $adb->device;
my $device = $adb->device(serial => 'emulator-5554');

say $device->serial;    # emulator-5554

Return a Net::ADB::Device instance bound to the selected device.

The serial is resolved when the instance is created, so the instance keeps talking to the same device even if other devices are connected later. If the device goes away (e.g. a wireless debugging device reconnects with a new port), its methods croak and a new instance is needed.

Accepts the "DEVICE SELECTION" parameters.

features

my @features = $adb->features;
my $features = $adb->features(serial => 'emulator-5554');    # array reference

if (grep { $_ eq 'shell_v2' } @features) { ... }

Return the list of features supported by the device (e.g. shell_v2, cmd, stat_v2), or an array reference in scalar context.

Accepts the "DEVICE SELECTION" parameters.

Same as adb features, host:features service.

state

my $state = $adb->state(usb => 1);    # device

Return the state of the device (device, offline, unauthorized, bootloader, recovery, ...).

Accepts the "DEVICE SELECTION" parameters.

Same as adb get-state, host:get-state service.

serialno

my $serial = $adb->serialno(usb => 1);

Return the serial of the device. Useful to resolve usb or tcp to a serial.

Accepts the "DEVICE SELECTION" parameters.

Same as adb get-serialno, host:get-serialno service.

devpath

my $devpath = $adb->devpath(usb => 1);    # usb:1-1

Return the device path (the USB port for USB devices).

Accepts the "DEVICE SELECTION" parameters.

Same as adb get-devpath, host:get-devpath service.

Port forwarding

forward

# Forward local port 8080 to port 80 on the device
$adb->forward(local => 'tcp:8080', remote => 'tcp:80');

# Let the server choose a free local port
my $port = $adb->forward(local => 'tcp:0', remote => 'tcp:80');

# Fail if tcp:8080 is already forwarded
$adb->forward(local => 'tcp:8080', remote => 'tcp:80', norebind => 1);

Forward connections from local (on the host) to remote (on the device). When a new TCP forward is created, return the local port, which is useful with tcp:0. A forward with the same local is replaced, unless norebind is set.

Allowed parameters:

  • local, local socket specification, e.g. tcp:<port> (tcp:0 chooses a free port), localabstract:<name>, localfilesystem:<path> (required).

  • remote, remote socket specification, e.g. tcp:<port>, localabstract:<name>, jdwp:<pid> (required).

  • norebind, croak if local is already forwarded (default: 0).

Accepts the "DEVICE SELECTION" parameters.

Same as adb forward, host:forward service.

killforward

$adb->killforward(local => 'tcp:8080');

Remove the forward of local (required) and return 1. Croaks if local is not forwarded.

Accepts the "DEVICE SELECTION" parameters.

Same as adb forward --remove, host:killforward service.

killforward_all

$adb->killforward_all;

Remove all forwards and return 1.

Accepts the "DEVICE SELECTION" parameters.

Same as adb forward --remove-all, host:killforward-all service.

list_forward

for my $forward ($adb->list_forward) {
    say "$forward->{serial} $forward->{local} $forward->{remote}";
}

Return the list of forwards (an array reference in scalar context), one hash reference per forward with serial, local and remote.

Accepts the "DEVICE SELECTION" parameters.

Same as adb forward --list, host:list-forward service.

Network

connect

$adb->connect(host => '192.168.0.10', port => 5555);
$adb->connect(host => '192.168.0.10:5555');

Connect to a device over TCP/IP and return the server message (e.g. connected to 192.168.0.10:5555). Croaks if the connection fails.

The device must listen on TCP/IP: enable it with adb tcpip 5555 over USB, or use the port shown by wireless debugging (Android 11+, see "pair").

Allowed parameters:

  • host, host name or IP address (IPv6 addresses are allowed), or host:port (required).

  • port, TCP port (default: 5555).

Same as adb connect, host:connect service.

disconnect

$adb->disconnect(host => '192.168.0.10', port => 5555);

# Disconnect all TCP/IP devices
$adb->disconnect;

Disconnect a TCP/IP device and return the server message (e.g. disconnected 192.168.0.10:5555). Without host, disconnect all TCP/IP devices. Croaks if the device is not connected.

Allowed parameters:

  • host, host name or IP address, or host:port.

  • port, TCP port (requires host).

Same as adb disconnect, host:disconnect service.

pair

my $message = $adb->pair(host => '192.168.0.10', port => 37099, code => '123456');

$adb->connect(host => '192.168.0.10', port => 41235);

Pair with a device using wireless debugging (Android 11+) and return the server message (e.g. Successfully paired to 192.168.0.10:37099 [guid=...]). Croaks if the pairing fails.

The pairing port and code are shown by "Pair device with pairing code" in the wireless debugging settings. They differ from the port used by "connect", which is shown on the main wireless debugging screen.

Allowed parameters:

  • host, host name or IP address, or host:port (required).

  • port, pairing port.

  • code, pairing code (required).

Same as adb pair, host:pair service.

Shell

shell_v2

my $res = $adb->shell_v2(command => 'ls /sdcard', timeout => 30);

if ($res->is_error) {
    die 'ls failed: ' . $res->stderr;
}

print $res->stdout;

Run command on the device with the shell protocol v2 and return a Net::ADB::Shell::Result instance (output, error output, exit code and duration).

The command is run by the device shell (/system/bin/sh), so it can contain pipes and redirections, and quoting is up to the caller. The output is returned as bytes, without any decoding.

Requires the shell_v2 feature (Android 7.0+, see "features").

Allowed parameters:

  • command, command to run (required).

  • timeout, timeout in seconds for this call (default: the timeout of "new").

Accepts the "DEVICE SELECTION" parameters.

Same as adb shell, shell,v2: service.

RETURN VALUES

"devices", "features" and "list_forward" return a list in list context and an array reference in scalar context. Inside a hash constructor or an argument list the context is list, so use scalar to get the reference:

my %report = (devices => scalar $adb->devices);

ERRORS

All methods croak on error, with the server message when available (e.g. adb FAIL: device 'emulator-5554' not found):

my $state = eval { $adb->state(serial => $serial) } or warn "Device not available: $@";

LOGGING

Net::ADB logs via Log::Any. Messages are discarded unless the application selects an adapter:

use Log::Any::Adapter ('Stderr', log_level => 'debug');

SEE ALSO

SUPPORT

Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker at https://github.com/giterlizzi/perl-Net-ADB/issues. You will be notified automatically of any progress on your issue.

Source Code

This is open source software. The code repository is available for public review and contribution under the terms of the license.

https://github.com/giterlizzi/perl-Net-ADB

git clone https://github.com/giterlizzi/perl-Net-ADB.git

AUTHOR

  • Giuseppe Di Terlizzi <gdt@cpan.org>

LICENSE AND COPYRIGHT

This software is copyright (c) 2026 by Giuseppe Di Terlizzi.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)