Summary
Add forward port management APIs to Xamarin.Android.Tools.AdbRunner, mirroring the reverse-port API added in #305. adb forward is sometimes the right primitive for hot-reload tunnels (ServiceHub forwardPort), and is needed by the MAUI DevTools CLI as a sibling of the existing reverse-port surface.
Context
The MAUI DevTools CLI exposes a maui android port group for tunnel management. Reverse forwarding (reverse <local> <remote>) is already mappable via #305's ReversePortAsync. But forward forwarding (forward <local> <remote>, where local is on the host machine and remote is on the device) is the opposite primitive — used when something on the host needs to talk to a service running on the device.
Today we have to fall back to raw adb forward … invocations. See maui-labs#197 audit.
Proposed API
Mirrors the reverse-port API surface added in #305 for symmetry.
namespace Xamarin.Android.Tools;
public partial class AdbRunner
{
/// adb -s <serial> forward <local> <remote>
public virtual Task ForwardPortAsync(
string serial,
AdbPortSpec local,
AdbPortSpec remote,
CancellationToken cancellationToken = default);
/// adb -s <serial> forward --remove <local>
public virtual Task RemoveForwardPortAsync(
string serial,
AdbPortSpec local,
CancellationToken cancellationToken = default);
/// adb -s <serial> forward --remove-all
public virtual Task RemoveAllForwardPortsAsync(
string serial,
CancellationToken cancellationToken = default);
/// adb -s <serial> forward --list (returns rules for the matching serial)
public virtual Task<IReadOnlyList<AdbPortRule>> ListForwardPortsAsync(
string serial,
CancellationToken cancellationToken = default);
}
The existing AdbPortSpec and AdbPortRule types from #305 are reused — both forward and reverse use the same tcp:, localabstract:, localreserved:, localfilesystem:, dev:, jdwp: syntax.
adb forward --list global output (no serial filter) is emitted by adb as <serial> <local> <remote> per line. Filter to the requested serial in the implementation, matching the symmetry with ListReversePortsAsync.
Consumer
- MAUI DevTools CLI (dotnet/maui-labs) —
maui android port forward <local> <remote> [--device], maui android port forward --remove, --list, --clear-all. See maui-labs#197 audit.
- VS Code MAUI extension ServiceHub → CLI migration —
MauiAndroidPlatform.ts forwardPort() (used in some debugger configurations where the IDE host needs to connect to a device-side socket).
- DevFlow agent connect flow — when the agent listens on a device port and the host needs to reach it via a stable host-side port (alternative to the current reverse pattern).
Related
Summary
Add forward port management APIs to
Xamarin.Android.Tools.AdbRunner, mirroring the reverse-port API added in #305.adb forwardis sometimes the right primitive for hot-reload tunnels (ServiceHubforwardPort), and is needed by the MAUI DevTools CLI as a sibling of the existing reverse-port surface.Context
The MAUI DevTools CLI exposes a
maui android portgroup for tunnel management. Reverse forwarding (reverse <local> <remote>) is already mappable via #305'sReversePortAsync. But forward forwarding (forward <local> <remote>, where local is on the host machine and remote is on the device) is the opposite primitive — used when something on the host needs to talk to a service running on the device.Today we have to fall back to raw
adb forward …invocations. See maui-labs#197 audit.Proposed API
Mirrors the reverse-port API surface added in #305 for symmetry.
The existing
AdbPortSpecandAdbPortRuletypes from #305 are reused — bothforwardandreverseuse the sametcp:,localabstract:,localreserved:,localfilesystem:,dev:,jdwp:syntax.adb forward --listglobal output (no serial filter) is emitted by adb as<serial> <local> <remote>per line. Filter to the requestedserialin the implementation, matching the symmetry withListReversePortsAsync.Consumer
maui android port forward <local> <remote> [--device],maui android port forward --remove,--list,--clear-all. See maui-labs#197 audit.MauiAndroidPlatform.tsforwardPort()(used in some debugger configurations where the IDE host needs to connect to a device-side socket).Related