adb_utils 0.3.1
adb_utils: ^0.3.1 copied to clipboard
A Dart library for interacting with ADB (Android Debug Bridge) server and devices.
adb_utils #
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. - Phantom (UiAutomator Agent): Orquestrar instalação/start do agente de teste instrumentado e enviar ações JSON via TCP (
dumpWindow,clickByText).
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.3.1
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}
UiAutomator Agent (PhantomClient) #
Para automações de UI via agente instrumentado:
import 'package:adb_utils/adb_utils.dart';
import 'package:adb_utils/src/phantom/phantom_client.dart';
final adb = AdbClient();
final d = await adb.device();
final phantom = PhantomClient(device: d, port: 9008);
await phantom.startAgent(
'lib/src/phantom/apks/target.apk',
'lib/src/phantom/apks/agent.apk',
);
final xml = await phantom.dumpWindow();
final hierarchy = await phantom.dumpWindowHierarchy();
final clicked = await phantom.clickByText('Entrar');
print(xml);
print('rotation => ${hierarchy.rotation}');
print('clickByText => $clicked');
startAgent realiza, em sequência: push dos APKs para /data/local/tmp, instalação (pm install -t -r), force-stop do agente antigo, start do instrumented test em background (nohup ... &) e adb forward tcp:<port>.
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.