adb_utils

pub.dev Dart License: MIT

Biblioteca Dart para interagir com o servidor ADB (Android Debug Bridge) e dispositivos Android via protocolo socket nativo. Inspirada na biblioteca openatx/adbutils do Python.

Esta biblioteca se comunica diretamente com o servidor ADB local via TCP (127.0.0.1:5037), eliminando a necessidade de invocar processos shell (executáveis adb) de forma ineficiente a todo momento.


Recursos (Features)

  • Gestão de Dispositivos: Listar, conectar, desconectar e monitorar estado de dispositivos.
  • Execução Shell: Executar comandos, com captura de saída e códigos de erro (returnCode).
  • Instalação e Aplicativos: Instalar/desinstalar APKs (via streaming de bytes) e obter informações avançadas de apps (dumpsys).
  • Interação: Capturar tela (screenshot) em bytes nativos, simular toques, deslizes e teclas (keyevents).
  • Socket & Forwarding: Criar port forwards locais/reversos e até obter conexões Socket raw nativas para serviços dentro do dispositivo Android.
  • SYNC Nativo (Transferência de Arquivos): Enviar (push), ler (readBytes, readText) e consultar (stat) arquivos diretamente usando o protocolo ADB SYNC.

Primeiros Passos (Getting Started)

Requisitos

  • Dart SDK ^3.11.4
  • ADB (Android Debug Bridge) instalado no sistema e o servidor em execução (adb start-server).

Instalação

Adicione o pacote adb_utils ao seu arquivo pubspec.yaml:

dependencies:
  adb_utils: ^0.2.2

E instale rodando:

dart pub get

Uso (Usage)

Aqui está um exemplo rápido de como se conectar ao ADB e ler o modelo de um dispositivo:

import 'package:adb_utils/adb_utils.dart';

void main() async {
  final adb = AdbClient();

  // Listar todos os dispositivos conectados
  for (final d in await adb.deviceList()) {
    print('${d.serial} - ${d.state.name} - ${d.model ?? ''}');
  }

  // Obter um dispositivo (Lança erro se houver mais de um ou nenhum)
  final device = await adb.device();
  
  // Ler propriedades via `getprop` com cache nativo opcional
  print(await device.prop.model);        // ex: "Pixel 7"
  
  // Executar um comando shell
  print(await device.shell('uname -r')); // versão do kernel
}

API Detalhada

AdbClient

O AdbClient é a porta de entrada da biblioteca. Representa a conexão com o servidor do ADB na sua máquina.

final adb = AdbClient(
  host: '127.0.0.1',
  port: 5037,
  socketTimeout: Duration(seconds: 10),
);

// Obter dispositivo via serial ou ID de transporte
final d1 = await adb.device(serial: '8d1f93be');
final d2 = await adb.device(transportId: 24);

// Conectar via TCP (ex: adb connect)
await adb.connect('192.168.1.100:5555');

// Monitorar eventos de conexão/desconexão em tempo real
await for (final event in adb.trackDevices()) {
  print('${event.serial} conectado? ${event.present}');
}

AdbDevice

A classe AdbDevice representa um Android específico.

Shell & Propriedades

String out = await d.shell('ls -l /sdcard');

// O shell2 retorna um ShellResult com o código de saída (returnCode) e sucesso.
ShellResult result = await d.shell2('ls /root');
print(result.returnCode); // 0 = sucesso, outro = erro.

// Atalhos rápidos para propriedades (getprop)
print(await d.prop.sdkVersion); // ex: "33"

Informação de Tela e Screenshots

var (width, height) = await d.windowSize();
bool isScreenOn = await d.isScreenOn();

// Pega um print da tela diretamente em binário (sem salvar num arquivo no celular)
Uint8List png = await d.screenshot();

Toques e Teclas

await d.click(540, 960);
await d.swipe(100, 500, 100, 200, 0.3); // X,Y inicio -> X,Y fim em 0.3s
await d.sendKeys('Olá Mundo!');
await d.keyEvent('KEYCODE_HOME');

Gerenciamento de APK e Pacotes

// Instala APK por streaming de Socket (não precisa dar push no arquivo)
await d.install(
  apkPath: 'build/app.apk',
  replace: true, 
  grantAllPermissions: true,
);

await d.uninstall(packageName: 'com.example.app');

// Obter App ativo na tela
ForegroundAppInfo app = await d.appCurrent();

Transferência de Arquivos (AdbSync)

Operações via protocolo nativo de transferência ADB SYNC (adb.sync).

// PUSH (Local -> Android)
await d.sync.push('/caminho/local/file.txt', '/sdcard/file.txt');
await d.sync.push(Uint8List.fromList([...]), '/sdcard/data.bin'); // direto da memoria

// PULL (Android -> Local)
await d.sync.pull('/sdcard/config.json', '/caminho/local/config.json'); // salva direto no disco (streaming)

// READ (Android -> Memória Local)
Uint8List bytes = await d.sync.readBytes('/sdcard/config.json');
String texto    = await d.sync.readText('/sdcard/config.json');

// STAT (Ler informações de tamanho e modificação)
Map<String, int> info = await d.sync.stat('/sdcard/file.txt');
// retorna algo como: {'mode': 33188, 'size': 1024, 'mtime': 16843453}

Tratamento de Erros

A biblioteca encapsula retornos malsucedidos em três exceções baseadas em Exception no arquivo exceptions.dart:

Exceção Descrição
AdbError O servidor ADB retornou um status FAIL ou uma resposta malformada de protocolo.
AdbTimeout O socket atingiu o timeout limite ou uma conexão de shell perdeu acesso.
AdbInstallError Erro específico reportado por sessão de instalação (install).

Licença

Este projeto é distribuído sob a licença MIT.

Libraries

adb_utils
Dart library for interacting with ADB (Android Debug Bridge).