Здравствуйте! А кто знает как можно скачать картинку (например фото из инстаграмма) с помощью adb?
Тут есть способ парсинга ... возможно ли это как то применить к картинкам?
var a = project.Context["ADB"];
project.Lists["parse"].AddRange(a.Parse("//node[@resource-id='com.google.android.youtube:id/duration' and @class='android.widget.TextView']", "text", 0, 5)); //XPath, какой аттрибут парсить, Index, Секунды
Здравствуйте! А кто знает как можно скачать картинку (например фото из инстаграмма) с помощью adb?
Тут есть способ парсинга ... возможно ли это как то применить к картинкам?
var a = project.Context["ADB"];
project.Lists["parse"].AddRange(a.Parse("//node[@resource-id='com.google.android.youtube:id/duration' and @class='android.widget.TextView']", "text", 0, 5)); //XPath, какой аттрибут парсить, Index, Секунды
Друзья, прошу помощи
Задача: эмулировать новые образы телефонов (у каждого должны быть свои уникальные параметры imei, android id и тд + прокси). Устанавливать на них разные приложения, логиниться и их использовать. И сохранять эти образы каким-то образом. Т.е. поднял я образ нужного мне телефона, там уже залогинен, там уже прокси, который использовался ранее для конкретного образа телефона - поработал, сохранил обновленный образ и отложил до следующего раза
Как профили в зенно
Чтобы таких "телефонов" было несколько и с какой-то периодичностью работать в них
Вопросы:
1) Возможно ли вообще такое? Т.е. возможно ли сделать такие "слепки" телефонов, хранить их и поднимать, когда потребуются?
2) Чем пользоваться? Эмуляторами или реальными устройствами? Конечно, при условии, что один такой "образ" не будет равен 1 реальному телефону))
3) Куда посмотреть и где почитать? Прочитал всю "Управление любыми Android приложениями на смартфоне из ZP". Результата, который в статье описан, добился на реальном устройстве. Но как сделать требуемые "образы" - не понял.
Прочитал и эту тему и несколько других, но так и не понял, куда копать.
Прошу подсказать как это реализовать или хотя бы в какую сторону искать, т.к. совсем новичок в этой теме
Заключение.
Надеюсь моя статья облегчит вам работу с эмуляторами и поможет создать более совершенную схему взаимодействия с ними. Это лишь небольшая часть того, как можно взаимодействовать с эмуляторами. Каждый ваш голос за статью будет мотивировать меня делиться многими полезными фишками в следующих частях.
Спасибо за внимание, друзья!
И еще вопрос: project.Variables["event"].Value = Regex.Match(project.Variables["receiver"].Value, "(?<=mouse2 event).*").ToString().Trim(); //получение № ивэнта
пустой результат, т.к. в переменной receiver нет ничего похожего на mouse2
И еще вопрос: project.Variables["event"].Value = Regex.Match(project.Variables["receiver"].Value, "(?<=mouse2 event).*").ToString().Trim(); //получение № ивэнта
пустой результат, т.к. в переменной receiver нет ничего похожего на mouse2
Due to a conflict between the adb integrated into the emulator and the one you installed. You just need to try replace adb from emulator folder to another folder.
Небольшое предисловие.
Обычно я стараюсь писать ботов на запросах, так как это не ресурсозатратно и в целом не сложно, если приложение слабозащищено.
Но бывают приложения, которые достаточно трудоёмко воспроизвести так, чтобы бот не умирал каждую неделю. Поэтому я решил, что некоторые вещи, например, регистраторы и фолловеры стоит делать используя автоматизацию эмуляторов.
В этой статье я поделюсь с вами своими наработками по автоматизации Android эмуляторов. И покажу как всё работает на примере эмулятора Nox и приложения Youtube.
Приступим.
Ранее я автоматизировал приложения через Appium, но меня не устраивали батники, запущенные окна cmd и невысокая гибкость всей системы в целом.
Поэтому я решил сделать автоматизацию напрямую, используя только ADB и UIAutomator. Для этого я использовал библиотеку SharpAdbClient.
Разделим статью на несколько частей для удобства:
Установка и настройка необходимого софта
Принцип работы. Разбор методов. XPath.
Определение адреса (ip:port) эмулятора, организация многопоточного режима и обработка зависаний.
Запускаем SDKManager и устанавливаем необходимые пакеты.
Прописываем пути до SDK (если их нет) в переменные среды:
Заходим в "Систему", через поиск Windows, либо комбинация клавиш Win + Pause/Break.
Дополнительные параметры системы
Переменные среды
Создаём переменную ANDROID_HOME и прописываем путь до папки с SDK.
В системной переменной Path прописываем пути до папки tools и platform-tools
Создаём ярлык для uiautomatorviewer.bat на рабочем столе, сам файл можно найти по пути "android-sdk/tools/uiautomatorviewer.bat", там куда вы установили AndroidSDK.
Запускаем uiautomatorviewer.bat для теста. Если появилось окно под названием UI Automator Viewer, значит всё хорошо.
Установка и настройка эмулятора и ZennoPoster:
Перемещаем библиотеки (.dll) из ExternalAssemblies в директорию ZennoPoster
Запускаем MultiDrive и создаём 3 эмулятора для теста (для удобства в настройках можно выставить телефонную ориентацию)
Добавляем шаблон в ZennoPoster. Прописываем необходимые пути в настройках (nox_adb.exe и nox.exe в папке bin).
Запускаем последовательно 3 эмулятора, затем устанавливаем 3 потока в ZennoPoster, и запускаем для теста. Должна пойти автоматизация в Youtube.
2. Принцип работы. Разбор методов. XPath.
Как получается связать adb с эмулятором без посредника (например Appium)?
У adb есть множество команд для управления Android. Например, команда
cmd.exe:
adb shell input tap x y
позволяет нам тапнуть по указанным координатам.
Соответственно, чтобы тапнуть по нужному элементу, нам надо узнать координаты этого элемента.
На эмуляторе по умолчанию предустановлен UIAutomator, поэтому вы можете получать данные видимых элементов с помощью команды:
cmd.exe:
adb shell uiautomator dump
Но в таком случае XML сохранится в корневой папкe Android, и придется скачивать его на ПК для просмотра - это долго и неудобно, поэтому добавим к команде /dev/tty.
Теперь команда будет выглядеть так:
cmd.exe:
adb shell uiautomator dump /dev/tty
Таким образом, мы выведем содержимое XML файла в лог, в этом случае библиотека SharpAdbClient подцепит ответ и мы сможем извлечь необходимые координаты.
Приведу небольшой список часто используемых команд, которые поддерживает adb:
cmd.exe:
adb help //вывести весь список комманд
adb start-server //запустить adb сервер
adb kill-server //закрыть adb сервер
adb connect <ip:port> //подключиться к устройству
adb devices //показать список подключенных устройств
adb reboot //перезагрузить устройство
adb install <path to .apk> //установить .apk файл
adb shell // Запускать команды через терминал Shell
adb shell input x y //тапнуть по координатам
adb shell input swipe x1 y1 x2 y2 sss //свайпнуть по координатам, где sss - скорость в миллисекундах
adb shell input text <string> //отправить текст
adb shell input keyevent <event_code> //отправить event (полный список event'ов будет ниже)
adb shell pm list packages //показать установленные пакеты
adb shell pm uninstall <com.your.app> //удалить пакет
adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp' //показать название текущей активности
Все остальные команды можно найти в поисковике, достаточно написать "adb commands list".
Теперь перейдем к шаблону.
В GAC уже добавлены необходимые .dll, а в директиве using и общем коде добавлены необходимые пространства имён.
Директивы using и общий код:
using SharpAdbClient;
using System.Net;
using System.Xml;
using System.Windows.Forms;
using System.Diagnostics;
using System.Management;
Команды adb теперь можно пропустить через подключенную библиотеку SharpAdbClient.
В общем коде я написал методы для удобства, обзор которых будет на видео в конце статьи.
Пройдемся по готовым кубикам.
Начнём с проверки запущен ли adb сервер по пути из переменной settings_adb:
if (!AdbServer.Instance.GetStatus().IsRunning) {
AdbServer server = new AdbServer();
var result = server.StartServer(project.Variables["settings_adb"].Value, restartServerIfNewer: false);
throw new Exception("Restart.");
}
Подключаемся к ip:port эмулятора. Обычно он автоматически подключается, но подстрахуемся командой:
Cоздаём объект ADB и сохраняем его в контексте, чтобы использовать далее в проекте:
C#:
ADB a = new ADB(project);
project.Context["ADB"] = a;
Создаём объект PackageManager, который позволит нам Удалять/Устанавливать приложение в этом же сниппете:
C#:
var a = project.Context["ADB"];
var device = a.Device();
SharpAdbClient.DeviceCommands.PackageManager manager = new SharpAdbClient.DeviceCommands.PackageManager(device);
try {
manager.UninstallPackage("com.google.android.youtube"); //удаление пакета
} catch (Exception e) {}
manager.InstallPackage(project.Directory + @"\youtube.apk", reinstall: false); //установка apk
Осуществляем запуск приложения:
C#:
var a = project.Context["ADB"];
a.StartApp("com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity"); //запуск приложения
// в CMD получить наименование текущего окна, которое нужно вставить в этот запрос
// adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp'
Ожидаем появление элемента:
C#:
var a = project.Context["ADB"];
a.Wait("//node[@resource-id='' and @class='android.widget.ImageView']", 0, 10); //XPath, Index, Секунды
Тапаем на элемент:
C#:
var a = project.Context["ADB"];
a.Click("//node[@resource-id='com.google.android.youtube:id/menu_search' and @class='android.widget.TextView']", 0, 10); //XPath, Index, Секунды
Обратите внимание, здесь впервые мы используем XPath для поиска объекта.
Учимся составлять свой XPath (это несложно):
Для начала запустим Nox и убедимся, что он подключен к adb.
Если подключенных устройств нет, тогда придется подключить эмулятор самостоятельно с помощью команды:
cmd.exe:
adb connect 127.0.0.1:62001
Вы должны получить сообщение о подключении. Обычно порт первого эмулятора 62001, но в моём случае 62025. Посмотреть вложение 56002
Если не получается поймать порт, то пробуйте перебор от 62001 до 62100.
Теперь установим и запустим youtube.apk из архива, а затем запустим uiautomatorviewer.bat и сделаем dump окна.
Вы можете поводить курсором по элементам и заметите, что в правой части окна выделяются соответствующие узлы (node). Соответственно, чтобы составить XPath мы должны выделить нужный нам элемент и взять атрибуты, которые могут идентифицировать элемент в дереве.
Составим XPath для лупы (поиск), взяв атрибуты resource-id и class:
XPath:
//node[@resource-id='com.google.android.youtube:id/menu_search' and @class='android.widget.TextView']
Если случается, что элемент невозможно идентифицировать (не указаны атрибуты), то в таком случае можно составить длинный XPath, например до элемента Home слева от лупы:
XPath:
//node[@resource-id='com.google.android.youtube:id/toolbar' and @class='android.view.View']/node[@class='android.widget.TextView']
Так же случаются ситуации, когда вам нужно сделать двойной тап или другие действия, которых нет в списке.
На помощь приходит команда sendevent:
cmd.exe:
adb shell sendevent /dev/input/event<x>
Получаем координаты элемента, с помощью метода получения координат.
Вы можете получать "чистые" координаты, либо уже высчитанную рандомную точку. В нашем случае используем сразу второй вариант:
C#:
var a = project.Context["ADB"];
string coord = a.GetCoord("//node[@resource-id='com.google.android.youtube:id/channel_avatar' and @class='android.widget.ImageView']", 0, 10, true); //XPath, Index, Секунды, рандомная точка между x1,y1 и x2,y2
string[] coords = coord.Split(new char[] {','});
project.Variables["x"].Value = coords[0];
project.Variables["y"].Value = coords[1];
Введем команду в cmd, кликнем на эмуляторе и запишем событие:
cmd.exe:
adb shell getevent
Вы получите значения в HEX, преобразуем их в DEC с помощью любого сервиса.
Получится:
var a = project.Context["ADB"];
a.Swipe("200", "600", "200", "200", "900"); //координаты x1, y1, x2, y2, sss - скорость в милисекундах
Также можно спарсить что-нибудь. Спарсим длительность видимых роликов (результат появится в списке шаблона):
C#:
var a = project.Context["ADB"];
project.Lists["parse"].AddRange(a.Parse("//node[@resource-id='com.google.android.youtube:id/duration' and @class='android.widget.TextView']", "text", 0, 5)); //XPath, какой аттрибут парсить, Index, Секунды
Button Back:
C#:
var a = project.Context["ADB"];
a.Back();
Button Home и Kill Process:
C#:
var a = project.Context["ADB"];
a.Home(); //Свернуть все окна
a.Kill("com.google.android.youtube"); //Убить процесс
Перезагрузить Android:
C#:
var a = project.Context["ADB"];
a.Reboot();
Загрузка файла. Я написал 2 метода для загрузки файла: обычная загрузка
C#:
var a = project.Context["ADB"];
a.UploadFile("/storage/sdcard0/ZennoLab.txt", project.Directory + @"\ZennoLab.txt");
и из переменной.
C#:
var a = project.Context["ADB"];
a.UploadFromVar("/storage/sdcard0/ZennoLab.txt", "ZennoLab TEST");
Скачивание файла:
C#:
var a = project.Context["ADB"];
a.DownloadFile("/storage/sdcard0/ZennoLab.txt", project.Directory + @"\Download_test.txt");
Удаление Файла:
C#:
var a = project.Context["ADB"];
a.Command("rm -rf /storage/sdcard0/ZennoLab.txt", false);
3. Определение IP+PORT эмулятора, организация многопоточного режима и обработка зависаний.
Для организации многопоточного режима я решил использовать залоченную глобальную переменную, в которой будут записаны id процессов (pid) окон эмуляторов через ";".
Когда шаблон запускается, то в глобальную переменную записывается pid первого по списку свободного эмулятора. Если в переменной не было этого pid, то другой поток не будет работать с этим pid.
Сам pid можно найти в Диспетчере задач (Ctrl+Shift+Esc).
(В этом способе есть один минус. Если вы прерываете работу шаблона вручную, то pid не удаляется. Буду рад вашим идеям решения этой проблемы в комментариях.)
Порой случается, что эмулятор зависает, для этого я использую метод CommandLineUtilities, прописанный в общем коде, чтобы записать все процессы связанные с эмулятором, закрыть и открыть их заново.
Закрываем процессы:
C#:
Process[] processes = Process.GetProcessesByName("Nox");
var ids = processes.Select(p => p.Id);
var process = Process.GetProcessById(int.Parse(project.Variables["process"].Value));
string name = Regex.Match(CommandLineUtilities.getCommandLines(process), "(?<=--comment ).*(?= --startvm)").ToString();
project.SendInfoToLog(CommandLineUtilities.getCommandLines(process));
foreach(int processId in ids){
var nox = Process.GetProcessById(processId);
if (Regex.Match(CommandLineUtilities.getCommandLines(nox),"(?<=-clone:).*").ToString().Contains(name)){
project.Variables["start_cmd"].Value = CommandLineUtilities.getCommandLines(nox);
nox.Kill();
break;
}
}
process.Kill();
Открываем эмулятор заново:
C#:
var proc = System.Diagnostics.Process.Start(project.Variables["settings_nox"].Value, Regex.Match(project.Variables["start_cmd"].Value, "-clone:.*").ToString());
Заключение.
Надеюсь моя статья облегчит вам работу с эмуляторами и поможет создать более совершенную схему взаимодействия с ними. Это лишь небольшая часть того, как можно взаимодействовать с эмуляторами. Каждый ваш голос за статью будет мотивировать меня делиться многими полезными фишками в следующих частях.
Спасибо за внимание, друзья!
статья огонь, реализовал то что нужно с помощью memu (memuc), но есть вопрос, в 2 потока есть понимание как работать, а вот в 3 и более происходят разногласия адб с нужной виртуальной машиной, подскажите пожалуйста решение :3
статья огонь, реализовал то что нужно с помощью memu (memuc), но есть вопрос, в 2 потока есть понимание как работать, а вот в 3 и более происходят разногласия адб с нужной виртуальной машиной, подскажите пожалуйста решение :3
Спасибо. Как-то через списки или глобальные переменные. Нужно зацепиться за какой-то параметр эмулятора и держать его в листе ожидания, пока он не выполнит задачу.
Спасибо. Как-то через списки или глобальные переменные. Нужно зацепиться за какой-то параметр эмулятора и держать его в листе ожидания, пока он не выполнит задачу.
благодарю, дружище еще момент, при парсинге, viewer не всегда по неизвестной мне причине выдает какой - либо "текст", а мне нужно спарсить его для создания исключения, иногда текст появляется в нодах, но чаще всего нет, в чем причина? спасибо
благодарю, дружище еще момент, при парсинге, viewer не всегда по неизвестной мне причине выдает какой - либо "текст", а мне нужно спарсить его для создания исключения, иногда текст появляется в нодах, но чаще всего нет, в чем причина? спасибо
У кого-нибудь была такая ошибка? Вылазит при попытке обновления в uiautomatorviewer, но только на некоторых страницах приложения Посмотреть вложение 75049
Чтобы не было ошибки, вводите текст через adb с помощью этого сниппета:
C#:
var sv = project.Variables["sv"].Value;
//sv это серийник устройства для многопотока вида 127.0.0.1:21521
ProcessStartInfo startInfo1 = new ProcessStartInfo();
startInfo1.FileName = "adb.exe";
startInfo1.Arguments = "-s "+sv+" shell am broadcast -a ADB_INPUT_TEXT --es msg 'ТУТ ВВОДИМЫЙ ТЕКСТ'";
startInfo1.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo1).WaitForExit();