Guias
Tutorial ADB Python: controlar um emulador Android
Um tutorial de adb com Python para o MAS: toque, deslize, digite, aperte teclas e tire capturas de tela no BlueStacks, com o adb gerenciado pelo app.
- Windows
- Mac
- Emulador
- Dispositivo na nuvem
- Celular
- SDK Python
Nesta página
- Antes de começar
- Como as peças se encaixam
- Criar o projeto
- Tamanho da tela e coordenadas
- Tirar uma captura de tela com adb em Python
- Tocar
- Deslizar
- Digitar
- Apertar teclas
- Abrir e verificar apps
- Um script completo
- Onde o adb entra neste tutorial Python
- O que pode dar errado
- Could not discover RPC port
- Os toques caem no lugar errado
- input_text não digitou nada
- Dispositivo não encontrado ou offline
A maioria dos tutoriais de adb com Python termina em um wrapper de subprocess em volta de adb shell input tap. Este tutorial de adb Python para o Macro Automation Studio (MAS) segue outro caminho: o app é dono do adb, e o seu script fala com o app pelo pacote mas. Este guia vai de um projeto novo até um script que abre um app, pesquisa um termo, rola a tela e salva uma captura. Ele é para desenvolvedores Python que querem controlar BlueStacks, LDPlayer, MuMu Player ou MEmu sem escrever chamadas de adb.
Antes de começar
- O MAS está instalado e você fez login com o teste ou um plano. Veja Instalar o MAS.
- Um emulador está aberto com o ADB ativado e adicionado como dispositivo em Grupos de dispositivos. Veja Dispositivos.
- Você conhece o básico de Python. Você não instala mais nada: o MAS traz o próprio ambiente Python 3.13 com o
masdentro.
Como as peças se encaixam
O MAS inicia o seu script como python -u -m src.app com a pasta do projeto como diretório de trabalho. Ele passa os dados de conexão em variáveis de ambiente (MAS_RPC_PORT, MAS_RPC_HOST, MAS_DEVICE_ID, MAS_SESSION_TOKEN). Toda chamada mas.* vira uma requisição JSON-RPC 2.0 para o app. O app roda o comando adb, a busca de template ou o OCR, e devolve o resultado. O dispositivo é vinculado antes de a sua primeira linha rodar, então não há chamada connect() nem serial para gerenciar. Veja Conceitos.
Criar o projeto
- Abra Macros e clique em Criar novo projeto.
- Escolha Baseado em código, defina Dispositivo alvo como mobile, dê um nome ao projeto e clique em Criar projeto.
- Abra o projeto. O Code Editor mostra
src/app.py. - Escolha o emulador no seletor de dispositivo e clique em Executar (F5) sempre que quiser testar um trecho. Parar é Shift+F5.
Tamanho da tela e coordenadas
Toda coordenada que você passa ao SDK é um deslocamento em pixels a partir do canto superior esquerdo da tela do dispositivo, na resolução do próprio dispositivo. O tamanho da janela do emulador no seu monitor não importa.
import mas
size = mas.get_screen_size()
print(f"Screen: {size.width}x{size.height}")
center = (size.width // 2, size.height // 2)
mas.click(*center)get_screen_size() retorna um ScreenSize com width e height. get_device_info() retorna o mesmo mais o name, o type e a flag connected do dispositivo. Quando um script precisa sobreviver a uma mudança de resolução, calcule as posições como frações do tamanho, como o exemplo do final faz. Imagens template e regiões de OCR não sobrevivem a isso; veja o guia de reconhecimento de imagem.
Tirar uma captura de tela com adb em Python
import base64
import mas
shot = mas.take_screenshot()
print(shot.width, shot.height, shot.timestamp)
with open("screen.png", "wb") as f:
f.write(base64.b64decode(shot.base64))take_screenshot() retorna um Screenshot: base64 contém um PNG, width e height são o tamanho em pixels, e timestamp é uma string ISO 8601. O arquivo acima cai na pasta do projeto porque esse é o diretório de trabalho. Passe o mesmo objeto a várias chamadas de find_object com screenshot=shot e todas buscam em um único quadro em vez de capturar de novo.
Tocar
mas.click(270, 800) # tap, then wait 1000 ms
mas.click(270, 800, delay_ms=300) # shorter pause for tight loopsclick(x, y, delay_ms=1000) toca uma vez e espera delay_ms depois para o app reagir. Não há duração de pressionamento em um toque; para um toque longo, use key_press com duration_ms.
Deslizar
mas.swipe((270, 750), (270, 300), duration_ms=400) # scroll a list down: drag from lower to upper
mas.swipe((100, 500), (400, 500), duration_ms=1000) # drag and drop: slow and deliberateswipe(from_coords, to_coords, duration_ms=1000) recebe duas tuplas (x, y). Uma duração curta é um flick; uma longa é um arrasto. Gestos de pinça são chamadas separadas: zoom_in() e zoom_out() usam por padrão o centro da tela com percent=50.
Digitar
mas.click(270, 120, delay_ms=500) # focus the field first
mas.input_text("hello world")
mas.input_text("new value", clear=True) # replace what is thereinput_text(text, delay_ms=0, clear=False) digita no campo em foco, então toque no campo antes. clear=True move o cursor para o fim e apaga os caracteres existentes antes de digitar.
Apertar teclas
from mas import KeyCode
mas.key_press(KeyCode.BACK)
mas.key_press(KeyCode.HOME)
mas.key_press(KeyCode.ENTER)
mas.key_press(KeyCode.DELETE, repeat=10) # ten presses in one command
mas.key_press(KeyCode.POWER, duration_ms=3000) # long presskey_press(key_code, modifiers=None, duration_ms=100, repeat=1) envia um evento de tecla do Android. Um duration_ms de 500 ou mais vira um toque longo; o número exato de milissegundos além disso não é respeitado. repeat vai de 1 a 100 e é muito mais rápido que um loop em Python. KeyCode também tem as teclas do D-pad, de volume, de mídia e numéricas.
Abrir e verificar apps
mas.open_app("com.android.settings", timeout_ms=5000)
print(mas.get_current_app()) # package name in front
print(mas.is_app_focused("com.android.settings")) # True or False
if mas.get_app_state("com.android.chrome") == mas.NOT_RUNNING:
mas.open_app("com.android.chrome")
mas.close_app("com.android.settings")open_app(package_name, timeout_ms=2000) abre pelo nome do pacote e espera timeout_ms. Para descobrir o nome de um pacote, abra o app à mão e imprima mas.get_current_app(). get_app_state retorna NOT_INSTALLED, NOT_RUNNING, RUNNING_IN_BACKGROUND_SUSPENDED, RUNNING_IN_BACKGROUND ou RUNNING_IN_FOREGROUND. close_app força a parada do pacote.
Um script completo
O script abre as Configurações do Android, pesquisa um termo, rola os resultados, salva uma captura de tela e confere com OCR que o termo está na tela. A caixa de pesquisa é um template que você recorta no Asset Lab; troque o ID pelo seu. O deslize usa frações do tamanho da tela para funcionar em qualquer resolução.
import base64
import sys
import time
import mas
from mas import KeyCode
PACKAGE = "com.android.settings"
TERM = "Display"
images = mas.images({"search_box": 301})
def main():
size = mas.get_screen_size()
mas.log(f"Screen {size.width}x{size.height}")
mas.open_app(PACKAGE, timeout_ms=5000)
if not mas.is_app_focused(PACKAGE):
mas.log(f"{PACKAGE} did not come to the front", level="error")
sys.exit(2)
box = mas.find_object_retry(images.search_box, total_tries=3, time_sleep=2.0)
if box is None:
mas.log("Search box not found; crop it in Asset Lab", level="error")
sys.exit(2)
mas.click(box.x, box.y, delay_ms=800)
mas.input_text(TERM, clear=True)
mas.key_press(KeyCode.ENTER)
time.sleep(2)
x = size.width // 2
mas.swipe((x, int(size.height * 0.75)), (x, int(size.height * 0.35)), duration_ms=600)
time.sleep(1)
shot = mas.take_screenshot()
with open("search_results.png", "wb") as f:
f.write(base64.b64decode(shot.base64))
mas.log(f"Saved search_results.png ({shot.width}x{shot.height})")
text = mas.read_text(screenshot=shot, psm=11)
mas.log(f"Term on screen: {TERM.lower() in text.text.lower()}")
mas.key_press(KeyCode.HOME)
if __name__ == "__main__":
main()read_text com psm=11 lê texto esparso pelo quadro inteiro, o que serve para uma lista de resultados. O guia de OCR cobre regiões e modos para ler um único contador. Se preferir descrever a tarefa em vez de escrevê-la, o MAS Agent escreve esse tipo de script para você.
Onde o adb entra neste tutorial Python
Você nunca chama o adb, mas ele está fazendo o trabalho por baixo.
- Binário. O instalador traz o adb. No Windows, ele fica em
C:\ProgramData\MacroAutomationStudio\3rdparty, com uma cópia embutida como alternativa. No Mac, fica dentro do pacote do app, com o adb do Homebrew como alternativa. Nada entra no seu PATH. A página Instalação tem os detalhes. - Conexão. Os emuladores expõem o adb em uma porta TCP local. Quando você clica em Iniciar ou Executar, o MAS roda
adb connect 127.0.0.1:<port>para a porta do card do dispositivo e mantém essa sessão pela execução. - Entrada.
clickviraadb shell input tap,swipeviraadb shell input touchscreen swipe,input_textviraadb shell input text, ekey_pressviraadb shell input keyevent. Gestos de pinça são escritos direto no dispositivo de entrada de toque do emulador. - Tela.
take_screenshote todofind_objectcapturam comadb exec-out screencap -p, a forma segura para binário que não corrompe o PNG no Windows.get_screen_sizelêwm size;get_current_applê o gerenciador de janelas. - Apps.
open_appdispara a intent do launcher pelomonkeye recorre aam start;close_approdaam force-stop. - Servidores. O MAS roda o próprio servidor adb. Se um segundo adb no seu PATH iniciar o dele, os dois se substituem e o seu dispositivo cai para Conectando. A página Solução de problemas de ADB lista as correções, porta por porta.
Como o app faz tudo isso, um script escrito no BlueStacks roda sem alterações no LDPlayer, em um dispositivo na nuvem ou no seu próprio celular por uma porta local.
O que pode dar errado
Could not discover RPC port
O script foi iniciado de um terminal em vez de pelo MAS, então as variáveis de ambiente estão faltando. Rode com Executar no Code Editor ou por um card de dispositivo.
Os toques caem no lugar errado
Você está usando pixels da janela em vez de pixels do dispositivo, ou a resolução do emulador mudou. Imprima mas.get_screen_size() e compare com as coordenadas que você passa. As coordenadas do Asset Lab já são pixels do dispositivo.
input_text não digitou nada
Nenhum campo tinha foco. Toque no campo com click e dê a ele delay_ms=500 antes de digitar. Alguns apps abrem um teclado que cobre o campo; key_press(KeyCode.BACK) o fecha depois de digitar.
Dispositivo não encontrado ou offline
O ADB está desligado no emulador, a porta no card do dispositivo está errada, ou outro servidor adb assumiu. Siga a Solução de problemas de ADB.
Se o app que você controla é um jogo, trate-o com o mesmo cuidado que qualquer outra conta automatizada. Nenhuma ferramenta de automação é 100% livre de riscos, por isso automatize com responsabilidade e a seu próprio critério.
Próximos passos
Páginas relacionadas
Obrigado. Se algo estiver errado, conte para a gente no Discord.
Dúvidas? Pergunte no Discord