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:
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 asadb -s.usb, the only device connected via USB. Same asadb -d.tcp, the only device connected via TCP/IP (adb connect, wireless debugging, emulators). Same asadb -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:0chooses a free port),localabstract:<name>,localfilesystem:<path>(required).remote, remote socket specification, e.g.tcp:<port>,localabstract:<name>,jdwp:<pid>(required).norebind, croak iflocalis 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), orhost: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, orhost:port.port, TCP port (requireshost).
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, orhost: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: thetimeoutof "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)