2 место Автоматизация Android без посредников. Часть 1.

WLDN

Client
Регистрация
09.07.2015
Сообщения
290
Благодарностей
356
Баллы
63

55998


Привет, дорогие зенщики! :az:

Небольшое предисловие.
Обычно я стараюсь писать ботов на запросах, так как это не ресурсозатратно и в целом не сложно, если приложение слабозащищено.
Но бывают приложения, которые достаточно трудоёмко воспроизвести так, чтобы бот не умирал каждую неделю. Поэтому я решил, что некоторые вещи, например, регистраторы и фолловеры стоит делать используя автоматизацию эмуляторов.
В этой статье я поделюсь с вами своими наработками по автоматизации Android эмуляторов. И покажу как всё работает на примере эмулятора Nox и приложения Youtube. :al:

Приступим.
Ранее я автоматизировал приложения через Appium, но меня не устраивали батники, запущенные окна cmd и невысокая гибкость всей системы в целом.
Поэтому я решил сделать автоматизацию напрямую, используя только ADB и UIAutomator. Для этого я использовал библиотеку SharpAdbClient.

Разделим статью на несколько частей для удобства:
  1. Установка и настройка необходимого софта
  2. Принцип работы. Разбор методов. XPath.
  3. Определение адреса (ip:port) эмулятора, организация многопоточного режима и обработка зависаний.

1. Установка и настройка необходимого софта.

Установка UIAutomator для поиска элементов:
  • Скачиваем архив под статьёй и распаковываем.
  • Устанавливаем AndroidSDK. Eсли просит установить Java, то устанавливаем сначала её (jre-8u241-windows-x64.exe).
  • Запускаем SDKManager и устанавливаем необходимые пакеты.
    56231


    56232
  • Прописываем пути до SDK (если их нет) в переменные среды:
    • Заходим в "Систему", через поиск Windows, либо комбинация клавиш Win + Pause/Break.
    • Дополнительные параметры системы
    • Переменные среды
Создаём переменную ANDROID_HOME и прописываем путь до папки с SDK.
56235


В системной переменной Path прописываем пути до папки tools и platform-tools
56236
  • Создаём ярлык для uiautomatorviewer.bat на рабочем столе, сам файл можно найти по пути "android-sdk/tools/uiautomatorviewer.bat", там куда вы установили AndroidSDK.
  • Запускаем uiautomatorviewer.bat для теста. Если появилось окно под названием UI Automator Viewer, значит всё хорошо.

Установка и настройка эмулятора и ZennoPoster:
  • Перемещаем библиотеки (.dll) из ExternalAssemblies в директорию ZennoPoster
  • Скачиваем и устанавливаем Nox.
  • Запускаем 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 подцепит ответ и мы сможем извлечь необходимые координаты.
55999

Приведу небольшой список часто используемых команд, которые поддерживает 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:
56000
C#:
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#:
AdbClient.Instance.Connect(new DnsEndPoint("127.0.0.1", int.Parse(Regex.Match(project.Variables["device"].Value, "(?<=:).*").ToString())));

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 devices
Вы должны увидеть своё устройство в списке.
56001
Если подключенных устройств нет, тогда придется подключить эмулятор самостоятельно с помощью команды:
cmd.exe:
adb connect 127.0.0.1:62001
Вы должны получить сообщение о подключении. Обычно порт первого эмулятора 62001, но в моём случае 62025.
56002

Если не получается поймать порт, то пробуйте перебор от 62001 до 62100.
Теперь установим и запустим youtube.apk из архива, а затем запустим uiautomatorviewer.bat и сделаем dump окна.
56003
Вы можете поводить курсором по элементам и заметите, что в правой части окна выделяются соответствующие узлы (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']
Весь синтаксис XPath можно подсмотреть здесь.


Ввод текста и нажатие event'а (Enter):
C#:
var a = project.Context["ADB"];
a.Text("ZennoLab"); //ввод текста
a.KeyEvent("66"); //Enter
0 --> "KEYCODE_UNKNOWN"
1 --> "KEYCODE_MENU"
2 --> "KEYCODE_SOFT_RIGHT"
3 --> "KEYCODE_HOME"
4 --> "KEYCODE_BACK"
5 --> "KEYCODE_CALL"
6 --> "KEYCODE_ENDCALL"
7 --> "KEYCODE_0"
8 --> "KEYCODE_1"
9 --> "KEYCODE_2"
10 --> "KEYCODE_3"
11 --> "KEYCODE_4"
12 --> "KEYCODE_5"
13 --> "KEYCODE_6"
14 --> "KEYCODE_7"
15 --> "KEYCODE_8"
16 --> "KEYCODE_9"
17 --> "KEYCODE_STAR"
18 --> "KEYCODE_POUND"
19 --> "KEYCODE_DPAD_UP"
20 --> "KEYCODE_DPAD_DOWN"
21 --> "KEYCODE_DPAD_LEFT"
22 --> "KEYCODE_DPAD_RIGHT"
23 --> "KEYCODE_DPAD_CENTER"
24 --> "KEYCODE_VOLUME_UP"
25 --> "KEYCODE_VOLUME_DOWN"
26 --> "KEYCODE_POWER"
27 --> "KEYCODE_CAMERA"
28 --> "KEYCODE_CLEAR"
29 --> "KEYCODE_A"
30 --> "KEYCODE_B"
31 --> "KEYCODE_C"
32 --> "KEYCODE_D"
33 --> "KEYCODE_E"
34 --> "KEYCODE_F"
35 --> "KEYCODE_G"
36 --> "KEYCODE_H"
37 --> "KEYCODE_I"
38 --> "KEYCODE_J"
39 --> "KEYCODE_K"
40 --> "KEYCODE_L"
41 --> "KEYCODE_M"
42 --> "KEYCODE_N"
43 --> "KEYCODE_O"
44 --> "KEYCODE_P"
45 --> "KEYCODE_Q"
46 --> "KEYCODE_R"
47 --> "KEYCODE_S"
48 --> "KEYCODE_T"
49 --> "KEYCODE_U"
50 --> "KEYCODE_V"
51 --> "KEYCODE_W"
52 --> "KEYCODE_X"
53 --> "KEYCODE_Y"
54 --> "KEYCODE_Z"
55 --> "KEYCODE_COMMA"
56 --> "KEYCODE_PERIOD"
57 --> "KEYCODE_ALT_LEFT"
58 --> "KEYCODE_ALT_RIGHT"
59 --> "KEYCODE_SHIFT_LEFT"
60 --> "KEYCODE_SHIFT_RIGHT"
61 --> "KEYCODE_TAB"
62 --> "KEYCODE_SPACE"
63 --> "KEYCODE_SYM"
64 --> "KEYCODE_EXPLORER"
65 --> "KEYCODE_ENVELOPE"
66 --> "KEYCODE_ENTER"
67 --> "KEYCODE_DEL"
68 --> "KEYCODE_GRAVE"
69 --> "KEYCODE_MINUS"
70 --> "KEYCODE_EQUALS"
71 --> "KEYCODE_LEFT_BRACKET"
72 --> "KEYCODE_RIGHT_BRACKET"
73 --> "KEYCODE_BACKSLASH"
74 --> "KEYCODE_SEMICOLON"
75 --> "KEYCODE_APOSTROPHE"
76 --> "KEYCODE_SLASH"
77 --> "KEYCODE_AT"
78 --> "KEYCODE_NUM"
79 --> "KEYCODE_HEADSETHOOK"
80 --> "KEYCODE_FOCUS"
81 --> "KEYCODE_PLUS"
82 --> "KEYCODE_MENU"
83 --> "KEYCODE_NOTIFICATION"
84 --> "KEYCODE_SEARCH"
85 --> "TAG_LAST_KEYCODE"

Так же случаются ситуации, когда вам нужно сделать двойной тап или другие действия, которых нет в списке.
На помощь приходит команда 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 с помощью любого сервиса.
Получится:
Код:
/dev/input/event<N>: 1 330 1
/dev/input/event<N>: 3 58 1
/dev/input/event<N>: 3 53 <x>
/dev/input/event<N>: 3 54 <y>
/dev/input/event<N>: 0 2 0
/dev/input/event<N>: 0 0 0
/dev/input/event<N>: 0 2 0
/dev/input/event<N>: 0 0 0
/dev/input/event<N>: 1 330 0
/dev/input/event<N>: 3 58 0
/dev/input/event<N>: 3 53 0
/dev/input/event<N>: 3 54 38
/dev/input/event<N>: 0 2 0
/dev/input/event<N>: 0 0 0
Получаем номер event'a с помощью команды:
C#:
var a = project.Context["ADB"];
a.Command("cat /proc/bus/input/devices", true);
project.Variables["event"].Value = Regex.Match(project.Variables["receiver"].Value, "(?<=mouse2 event).*").ToString().Trim(); //получение № ивэнта

Тапаем с помощью sendevent, подставив номер event'а и координаты (в нашем случае двойной тап не нужен, поэтому я закомментил вторую часть в шаблоне):
C#:
var a = project.Context["ADB"];
string evnt = project.Variables["event"].Value;
string x = project.Variables["x"].Value;
string y = project.Variables["y"].Value;
a.Command(String.Format("sendevent /dev/input/event{0} 1 330 1", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 3 58 1", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 3 53 {1}", evnt, x), false);
a.Command(String.Format("sendevent /dev/input/event{0} 3 54 {1}", evnt, y), false);
a.Command(String.Format("sendevent /dev/input/event{0} 0 2 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 0 0 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 0 2 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 0 0 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 1 330 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 3 58 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 3 53 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 3 54 38", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 0 2 0", evnt), false);
a.Command(String.Format("sendevent /dev/input/event{0} 0 0 0", evnt), false);

Свайпаем:
C#:
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. :bf:
Сам pid можно найти в Диспетчере задач (Ctrl+Shift+Esc).
56004

Далее если ввести в cmd команду:
cmd.exe:
netstat -a -n -o
то высветится множество адресов, а в самой правой колонке мы увидем pid.
56005

Зная, что порты для подключение adb у Nox начинаются с 620, мы можем взять адрес по pid'у с помощью команды:
cmd.exe:
netstat -a -n -o | find "PID" | find "127.0.0.1" | find "620"
вместо PID подставив id процесса (pid).

Теперь сделаем тоже самое в зенке.
Инициализируем/проверяем существование глобальной переменной:
C#:
lock(SyncObject) {
    try {
        var gbVar = project.GlobalVariables["Zappium", "process"];
        return null;
    } catch (KeyNotFoundException ex) {
        string defaultValue = String.Empty;
        project.GlobalVariables.SetVariable("Zappium", "process", defaultValue);
    }
}

Получаем свободный PID с помощью стандартного инструментария .Net:
C#:
lock(SyncObject) {
var gbVar = project.GlobalVariables["Zappium", "process"];
Process[] processes = Process.GetProcessesByName("NoxVMHandle");
var ids = processes.Select(p => p.Id);
string process = "";
foreach(int processId in ids){
    project.SendInfoToLog(processId.ToString());
    process = processId.ToString();
    if (project.Variables["process"].Value == String.Empty && !project.GlobalVariables["Zappium", "process"].Value.ToString().Contains(process)){
        project.Variables["process"].Value = process;
        gbVar.Value = gbVar.Value + process + ";";
        }
}
}

Получаем адрес устройства, подставив pid в ранее написанную команду:
C#:
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();

cmd.StandardInput.WriteLine(String.Format("netstat -a -n -o | find \"{0}\" | find \"127.0.0.1\" | find \"620\"",project.Variables["process"].Value));

cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();

return "127.0.0.1:" + Regex.Match(cmd.StandardOutput.ReadToEnd(), "(?<=127.0.0.1:)62.*?(?= )");

По завершению работы шаблона удаляем из глобальной переменной pid, чтобы освободить окно для следующих потоков:
C#:
lock(SyncObject) {
    var gbVar = project.GlobalVariables["Zappium", "process"];
    gbVar.Value = gbVar.Value.ToString().Replace(project.Variables["process"].Value + ";", "");
}
(В этом способе есть один минус. Если вы прерываете работу шаблона вручную, то 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());



Заключение.
Надеюсь моя статья облегчит вам работу с эмуляторами и поможет создать более совершенную схему взаимодействия с ними. Это лишь небольшая часть того, как можно взаимодействовать с эмуляторами.
Каждый ваш голос за статью будет мотивировать меня делиться многими полезными фишками в следующих частях.
Спасибо за внимание, друзья! :bt:
 

Вложения

Последнее редактирование:

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113
Статья огонь!!! А как реализована работа через прокси для каждого эмулятора?
 
  • Спасибо
Реакции: WLDN

606

Client
Регистрация
07.03.2019
Сообщения
16
Благодарностей
2
Баллы
3
отличный старт)
 
  • Спасибо
Реакции: WLDN

WLDN

Client
Регистрация
09.07.2015
Сообщения
290
Благодарностей
356
Баллы
63
Статья огонь!!! А как реализована работа через прокси для каждого эмулятора?
Спасибо :-) В этой части пока что рассказываю про базовую автоматизацию, в след частях буду делиться своими решениями по прокси и другим полезным вещам.
 

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113
в след частях буду делиться своими решениями по прокси и другим полезным вещам.
будешь след. конкурс статей ждать? Это же полгода примерно. с учетом того, что конкурсы примерно раз в квартал проходят, и след. конкурс будет про шаблоны. К тому времени информация может немного устареть, используемая библиотека обновиться. А без прокси у каждого эмулятора будет один айпишник, что не есть гуд.
 
  • Спасибо
Реакции: WLDN

che100

Client
Регистрация
18.04.2017
Сообщения
386
Благодарностей
108
Баллы
43
Статья огонь!!! А как реализована работа через прокси для каждого эмулятора?
Можно через Proxy Droid.
Работа через эмулятор это здорово, но 2 момента смущают сходу, приложение может определить что оно запускается на эмуляторе и то что версии андроида такие древние, что в реальной жизни на таких никто не сидит.
 
  • Спасибо
Реакции: vertigo141

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113

Saavdav

Client
Регистрация
23.09.2019
Сообщения
44
Благодарностей
5
Баллы
8
Интересно, но для пользователя с хорошим опытом в програмировании. К сожалению тяжело усвоилось... Будем изучать) Спасибо за хорошую статью! Успехов
 
  • Спасибо
Реакции: WLDN

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113

nectah

Client
Регистрация
17.09.2010
Сообщения
75
Благодарностей
5
Баллы
8
предлагаешь расходится и не ждать остальных авторов? :ap:
я по андроиду только и ждал :ap: но лучшая статья там где дают пищу для размышлений, а не просто схему)
 
  • Спасибо
Реакции: WLDN

Nike59

Client
Регистрация
05.08.2011
Сообщения
120
Благодарностей
111
Баллы
43
Очень хорошее начало конкурса. Статья порадовала. Спасибо за подгон библиотеки для работы c# с adb. Почему-то думал, что достойной альтернативы appium нет. Все-таки appium - костыль. А тут напрямую идет работа с adb.
 
  • Спасибо
Реакции: WLDN

Dexio

Client
Регистрация
09.05.2014
Сообщения
1 219
Благодарностей
209
Баллы
63
Спасибо за шикарные сниппеты!
 
  • Спасибо
Реакции: WLDN

sergio197675

Client
Регистрация
21.09.2019
Сообщения
160
Благодарностей
135
Баллы
43
Благодарю автора! давно искал методы избавиться от cmd и аппиума)- в программировании я 0, все на кубиках))
Интересна была бы реализация и стабильность работы с физическими устройствами... у меня " ферма "-10 андроидов, но непериодические отвалы по юсб и зависания демонов adb) , те сырой шаблон "плугэндплей", прокси, смена ип..ссори пишу за рулём с телефона)
просьба добавить примеров с реальными устройствами!
Мой голос за вас , удачи!
 
Последнее редактирование:
  • Спасибо
Реакции: Earthshaker и WLDN

seregakot

Client
Регистрация
19.03.2016
Сообщения
100
Благодарностей
54
Баллы
28
Спасибо большое за очень интересный и познавательный материал.
Тоже думал как избавиться от аппиума и ошибок.
 
  • Спасибо
Реакции: WLDN

WLDN

Client
Регистрация
09.07.2015
Сообщения
290
Благодарностей
356
Баллы
63
будешь след. конкурс статей ждать? Это же полгода примерно. с учетом того, что конкурсы примерно раз в квартал проходят, и след. конкурс будет про шаблоны. К тому времени информация может немного устареть, используемая библиотека обновиться. А без прокси у каждого эмулятора будет один айпишник, что не есть гуд.
Согласен с тобой, что информация имеет свойство устаревать. К сожалению, времени, возможностей и желания хватило пока раскрыть эту сторону вопроса. :( Моё решение по прокси нужно хорошо обдумать, скомпоновать и потом уже выкладывать. Если к тому времени появится чьё-то решение, то я либо опущу этот вопрос, либо дополню его своим решением.

Вообще вижу, что ты тоже занимаешься автоматизацией Android, был бы рад, если бы ты смог поделиться в комментариях своим решением.
 
  • Спасибо
Реакции: FAQBILL и radv

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113
Вообще вижу, что ты тоже занимаешься автоматизацией Android, был бы рад, если бы ты смог поделиться в комментариях своим решением.
Насчет прокси пока тестирую разные варианты.
 
  • Спасибо
Реакции: WLDN

WLDN

Client
Регистрация
09.07.2015
Сообщения
290
Благодарностей
356
Баллы
63
вчера только мучался / https://t.me/zennolabchat/222939 и ждал что бы хоть кто то ответил / как найти элементы под таким слоем? https://prnt.sc/sidh4y
Привет, если uiautomator его не отображает, то нужно редактировать .jar. У меня были подобные небольшие проблемы, и я решил, что лучшим решением будет подредачить uiautomator.jar, либо заменить его на что-то более совершенное.
 

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113
Все-таки appium - костыль. А тут напрямую идет работа с adb.
В аппиуме идет работа с самими элементами. Я бы не сказал что это костыль, там можно и проверку наличия элементов делать и много всего. Конечно это может влиять на скорость работы, но зато повышает стабильность. В моем конструкторе есть работа и через адб и через аппиум без всяких дополнительных окон консоли и батников. Сейчас можно проверить и работу через описанную библиотеку и сравнить со своими методами работы с эмулятором.
 
  • Спасибо
Реакции: Nike59

limarkximus

Client
Регистрация
01.08.2019
Сообщения
111
Благодарностей
59
Баллы
28
ну во! таких бы статей поболее.. а не то как спамить дейт)
 
  • Спасибо
Реакции: 606 и WLDN

TazMan

Client
Регистрация
05.01.2017
Сообщения
112
Благодарностей
13
Баллы
18
Привет, если uiautomator его не отображает, то нужно редактировать .jar. У меня были подобные небольшие проблемы, и я решил, что лучшим решением будет подредачить uiautomator.jar, либо заменить его на что-то более совершенное.
не проще ли тогда будет отловить запросы на fiddler и сделать post-get? пересобирать apk как то не с руки :-) хотя как вариант наверное прокатит
 

WLDN

Client
Регистрация
09.07.2015
Сообщения
290
Благодарностей
356
Баллы
63
не проще ли тогда будет отловить запросы на fiddler и сделать post-get? пересобирать apk как то не с руки :-) хотя как вариант наверное прокатит
Если защита слабенькая, то конечно проще будет использовать этот вариант.
 

Nats1

Client
Регистрация
15.04.2015
Сообщения
149
Благодарностей
143
Баллы
43
Ждем рекапчи, фанкапчи и другие "закрутки" в мобильных прилах :D . Но статья хорошая.
 
  • Спасибо
Реакции: 606 и WLDN

mrboogie

Client
Регистрация
28.05.2019
Сообщения
15
Благодарностей
7
Баллы
3
Спасибо :-) В этой части пока что рассказываю про базовую автоматизацию, в след частях буду делиться своими решениями по прокси и другим полезным вещам.
Почему используешь UI Automator а не Appium?
 

WLDN

Client
Регистрация
09.07.2015
Сообщения
290
Благодарностей
356
Баллы
63
  • Спасибо
Реакции: mrboogie

radv

Client
Регистрация
11.05.2015
Сообщения
1 099
Благодарностей
553
Баллы
113
Кстати, стоит разделять Appium как софт и как dll. Так вот Appium(Софт) т.е. обертка-интерфейс над dll может помогать исследовать элементы вместо использования UI Automator, а вот если использовать саму dll с аппиумом, то можно все действия делать через C# код.
 

killer911

Client
Регистрация
23.03.2015
Сообщения
518
Благодарностей
106
Баллы
43
Спасибо за статью, Очень полезная информация! Но зачем ты сходу с козырей херачит? Таким скромным автором как я, даже неловко публиковаться(
Шучу
 
  • Спасибо
Реакции: WLDN и 606

Кто просматривает тему: (Всего: 2, Пользователи: 1, Гости: 1)