Guias
Multi-instância de emulador Android: farm com grupos
Farm multi-instância de emulador Android no MAS: adicione cada instância do BlueStacks ou LDPlayer pela porta, agrupe-as e dê a cada um seu perfil e proxy.
- Windows
- Mac
- Emulador
- Studio
- SDK Python
Nesta página
- Antes de começar
- Cada instância de um emulador Android multi-instância é um dispositivo
- Criar um grupo de dispositivos
- Dê a cada dispositivo os próprios argumentos
- Dê a cada dispositivo o próprio proxy
- Iniciar todos: sincronização multi-instância no LDPlayer ou BlueStacks
- Mantenha o estado por dispositivo com o armazenamento
- Webhooks por grupo
- Fique de olho nos limites de recursos de uma farm de bots no BlueStacks
- Agende o grupo
- Um exemplo completo
- O que pode dar errado
- A porta já está em uso
- Uma instância roda, as outras ficam em Conectando
- Os templates correspondem em uma única instância
- Toda instância compartilha um contador
Uma macro, cinco contas, um clique: isso é farm multi-instância de emulador Android. O Macro Automation Studio (MAS) trata toda instância de emulador como um dispositivo separado. Um grupo de dispositivos então roda a mesma macro em todas elas, com argumentos por dispositivo, um proxy para cada uma e um armazenamento que nunca mistura contadores. Este guia monta essa configuração no BlueStacks, LDPlayer, MuMu Player ou MEmu. Ele é para quem roda mais de uma conta.
Antes de começar
- O MAS está instalado e você fez login com um plano cuja contagem de dispositivos cobre as instâncias que você quer rodar ao mesmo tempo. Veja Cobrança.
- O gerenciador de multi-instâncias do emulador criou as instâncias e cada uma tem o ADB ativado. Os guias do BlueStacks, do LDPlayer, do MuMu Player e do MEmu mostram onde ficam a opção e a porta.
- Toda instância usa a mesma resolução e o mesmo DPI daquela em que você capturou os templates.
- A macro funciona em uma instância a partir do Code Editor. Veja o guia de loops.
Cada instância de um emulador Android multi-instância é um dispositivo
Uma instância de emulador escuta o adb na própria porta TCP local. O MAS encontra as instâncias escaneando os processos em execução e mantendo as portas dentro da faixa conhecida de cada emulador. Duas janelas do BlueStacks aparecem, portanto, como duas entradas na lista Porta. O dispositivo é a porta; o grupo é a lista de portas.
| Emulador | Portas que o MAS aceita |
|---|---|
| BlueStacks | 5555 a 8500 |
| LDPlayer | Portas ímpares de 5555 a 5599 |
| MuMu Player | Portas ímpares de 5555 a 5599, 7555, 16384 a 16576, 26624 a 27264 |
| MEmu | 21503 e toda porta terminada em 3 acima dela, abaixo de 30000 |
Mantenha toda instância aberta enquanto a adiciona; uma instância parada não tem porta para encontrar. A página Dispositivos tem as regras completas de descoberta.
Criar um grupo de dispositivos
- Abra Grupos de dispositivos e clique em Criar novo grupo.
- Digite um Nome, mantenha o tipo Local e clique em Criar grupo.
- Abra o grupo e clique em Adicionar dispositivo.
- Digite um Nome do dispositivo que diga qual conta é, por exemplo
farm-alt-2. - Escolha a porta da instância em Porta. Clique em Atualizar se ela não aparecer, ou escolha Porta personalizada e digite-a.
- Clique em Adicionar dispositivo e repita para cada instância.
- Em cada card de dispositivo, escolha a macro no seletor Macro.
Uma porta pode pertencer a um único dispositivo. Adicioná-la duas vezes falha com “Port is already in use”. Veja Grupos de dispositivos.
Dê a cada dispositivo os próprios argumentos
A maioria dos bots precisa de um valor que muda por conta: um nome, um alvo, um número de rodadas. Há duas formas de passá-lo.
Perfis de configurações (sem mudar o código). Se a macro tem um formulário de argumentos do UI Builder, cada card de dispositivo tem Editar argumentos. A caixa de diálogo traz uma barra Perfil: informe os valores, escolha Salvar os valores atuais como novo perfil, dê um nome e clique em Criar perfil. Um dispositivo segue um perfil, e editar o perfil atualiza todo dispositivo que o segue na próxima execução. O “Padrão” sempre existe e não pode ser excluído. Veja Perfis de configurações e UI Builder.
A porta no código. O script pode perguntar em qual instância está e escolher as próprias configurações. Isso não precisa de formulário e é o que o exemplo do final faz.
import mas
port = mas.get_current_device_port() # 5555, 5557, 5559 ...Use perfis quando os valores mudam com frequência ou outra pessoa roda o bot; use a porta quando o mapeamento é fixo e vive junto com o código.
Dê a cada dispositivo o próprio proxy
Contas que compartilham um IP compartilham o mesmo destino. O MAS anexa um proxy por dispositivo e roteia o tráfego daquela instância por ele.
- Abra Proxies. Em Adicionar um proxy, preencha a aba Conta do gateway, ou a aba Outro provedor para um proxy seu (
http,httpsousocks5), e clique em Adicionar e testar. - Aguarde o teste. Ele confirma que o proxy responde e detecta o país; Testar o repete depois.
- Clique em Atribuir e escolha o dispositivo, ou abra o card do dispositivo em Grupos de dispositivos e escolha o proxy em Proxy.
O card do dispositivo mostra o estado do proxy a cada execução, e os webhooks de execução carregam proxy_exit_ip e proxy_country. Um dispositivo tem um proxy; anexar outro substitui o anterior. Veja Proxies.
Iniciar todos: sincronização multi-instância no LDPlayer ou BlueStacks
Clique em Iniciar todos no topo do grupo. O MAS inicia os dispositivos um após o outro, com meio segundo de intervalo, cada um com a própria execução, o próprio log e o próprio código de saída. Um dispositivo sem macro é pulado com um erro e o resto continua. Parar todos encerra toda execução do grupo. A aba Logs de cada card mostra só aquele dispositivo, e a aba Dashboard mostra a interface de execução dele se a macro tiver uma.
Mantenha o estado por dispositivo com o armazenamento
mas.save, mas.retrieve e mas.clear são indexados por este computador, pela porta do dispositivo e por um nome de tarefa. Duas instâncias rodando a mesma macro mantêm, portanto, contadores separados sem código extra. Para somá-los, mas.retrieve_all(task_name) retorna uma entrada por porta com machine_id, port, data e updated_at.
TASK = "collector"
mine = mas.retrieve(TASK) # this instance only
everyone = mas.retrieve_all(TASK) # every instance on this computer
total = sum(entry["data"].get("done", 0) for entry in everyone)Veja Armazenamento.
Webhooks por grupo
Para ser avisado quando qualquer conta terminar ou falhar, adicione um endpoint na página Webhooks, escolha os eventos em Me envie, e em Me envie eventos de escolha Grupos específicos e marque o grupo. Os dispositivos que você adicionar ao grupo depois também ficam cobertos. Cada evento carrega device_name, device_port, group_id, status e exit_code, então um único endpoint consegue distinguir as contas. Veja Webhooks.
Fique de olho nos limites de recursos de uma farm de bots no BlueStacks
Toda instância é um sistema Android completo. Antes de escalar, confira três coisas:
- CPU e RAM por instância. Cada instância consome os núcleos e a memória definidos nas configurações de instância do emulador. Some tudo e deixe folga para o MAS, que roda o template matching e o OCR de toda instância na mesma máquina. Quando os toques começam a atrasar, você passou do limite.
- Dispositivos do seu plano. Um plano é dimensionado por quantos dos seus dispositivos podem rodar ao mesmo tempo. Iniciar todos roda quantos o plano permitir; veja Cobrança e a página de preços.
- Jobs agendados. O Agendador roda até 20 jobs de uma vez, um por porta.
Menos instâncias rodando limpas valem mais do que muitas instâncias errando templates.
Agende o grupo
O Agendador tem uma porta como alvo por job, então um agendamento de grupo é um job por dispositivo.
- Abra o Agendador e clique em Criar novo agendamento.
- Escolha a Macro, clique em Escanear em Porta do emulador e escolha a primeira instância.
- Defina Data, Hora e Recorrência, depois clique em Criar agendamento.
- Repita para cada porta. Dê aos jobs o mesmo horário; portas diferentes nunca colidem.
As execuções agendadas usam os argumentos salvos em cada card de dispositivo, ou o perfil que o dispositivo segue, então os valores por conta são mantidos. O app precisa ficar aberto. Veja Agendador e o guia de loops.
Um exemplo completo
A macro lê a própria porta, escolhe as configurações da conta, mantém um contador por porta e registra no fim o total de todas as instâncias. Troque as portas e os IDs de imagem pelos seus.
import random
import sys
import time
import mas
images = mas.images({
"collect": 501,
"close_popup": 502,
})
SETTINGS = { # per instance, keyed by the emulator's adb port
5555: {"account": "main", "rounds": 20},
5557: {"account": "alt-1", "rounds": 10},
5559: {"account": "alt-2", "rounds": 10},
}
DEFAULT = {"account": "unknown", "rounds": 5}
TASK = "collector"
TIME_BUDGET_S = 15 * 60
def main():
port = mas.get_current_device_port()
settings = SETTINGS.get(port, DEFAULT)
account = settings["account"]
mas.log(f"Port {port}: account {account}, {settings['rounds']} rounds")
done = mas.retrieve(TASK).get("done", 0)
started = time.monotonic()
misses = 0
while done < settings["rounds"]:
if time.monotonic() - started > TIME_BUDGET_S:
mas.log(f"{account}: time budget reached", level="warning")
break
popup = mas.find_object(images.close_popup)
if popup:
mas.click(popup.x, popup.y, delay_ms=800)
continue
button = mas.find_object_retry(images.collect, total_tries=3, time_sleep=2.0)
if button is None:
misses += 1
if misses >= 5:
mas.log(f"{account}: five misses, giving up", level="error")
sys.exit(2)
continue
misses = 0
mas.click(button.x, button.y, delay_ms=1000)
done += 1
mas.save(TASK, {"done": done, "account": account})
time.sleep(random.uniform(0.8, 2.5))
total = sum(entry["data"].get("done", 0) for entry in mas.retrieve_all(TASK))
mas.log(f"{account}: {done} rounds done; {total} across all instances")
mas.webhook("account.finished", {"account": account, "port": port, "done": done})
if __name__ == "__main__":
main()mas.webhook envia um evento custom.account.finished aos endpoints inscritos em eventos personalizados; tire a linha se você não tiver nenhum. Quando o mapeamento crescer, mova-o para um formulário de argumentos e leia args.<tab>.<key> em vez do dicionário.
O que pode dar errado
A porta já está em uso
Outro dispositivo em um dos seus grupos é dono dessa porta. Cada porta pode ser adicionada uma vez; remova a entrada antiga ou escolha a porta da outra instância.
Uma instância roda, as outras ficam em Conectando
As outras instâncias estão com o ADB desligado, ainda estão iniciando, ou escutam em portas fora da faixa do emulador. Abra as configurações de cada instância, confirme o ADB e a porta, e clique em Atualizar em Adicionar dispositivo. Se a porta fica fora da tabela acima, use Porta personalizada. Veja Solução de problemas de ADB.
Os templates correspondem em uma única instância
Aquela instância tem outra resolução ou DPI. O template matching é baseado em pixels; coloque toda instância na resolução da captura nas configurações de instância do emulador e reinicie. O guia de reconhecimento de imagem explica o resto.
Toda instância compartilha um contador
O script passa um port ou machine_id explícito a mas.save, ou usa um arquivo em disco em vez do armazenamento. Chame mas.save(TASK, data) com os padrões; a porta atual é adicionada para você.
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