Як я збудував мобільний автоматизатор з 150 000 рядків коду: Accessibility API, on-device AI та всі граблі на цьому шляху

💡 Усі статті, обговорення, новини про Mobile — в одному місці. Приєднуйтесь до Mobile спільноти!

Мене звати Василь. Я Android-розробник і автор застосунку Automator — Macro & AI Agent. Це не стаття про те, який я молодець. Це чесна розповідь про те, що таке мобільна автоматизація зсередини, чому це технічно складно, і які рішення я приймав на кожному етапі.

Ідея: автоматизувати все, що можна натиснути

Все починалось просто: я хотів автоматизувати рутинні дії на телефоні. Натискання, свайпи, заповнення форм, копіювання даних між застосунками. Те, що на десктопі давно вирішується скриптами — на Android завжди було болем.

Існуючі рішення або вимагали root-доступу, або були надто вузькоспеціалізованими, або просто погано працювали на сучасних версіях Android. Я вирішив зробити власне — і не підозрював, наскільки це виявиться глибокою кролячою норою.

Технічне ядро: Accessibility API і чому це нетривіально

Серце Automator — Android Accessibility API. Це системний інтерфейс, який Google створив для людей з особливими потребами: він дозволяє читати вміст екрану, клікати на елементи, вводити текст — без root.

Звучить просто. На практиці — зовсім ні.

Проблема перша: нестабільність дерева View. Кожен застосунок будує свій UI по-своєму. Один використовує стандартні View, інший — кастомні Canvas, третій — Flutter або React Native, які взагалі не дають нормального дерева елементів. Automator має вміти працювати з усіма цими варіантами. Це означало побудову власного механізму пошуку елементів з fallback-логікою: спочатку шукаємо по contentDescription, потім по text, потім по координатах через OCR.

Проблема друга: Android вбиває фонові процеси. Починаючи з Android 8, система агресивно чистить пам’ять. Служба автоматизації, яка має виконувати макрос через годину — може просто не існувати. Довелось реалізувати механізм Foreground Service з постійним сповіщенням, wake lock менеджментом і відновленням після перезапуску.

Проблема третя: координати vs елементи. Деякі дії простіше виконати через координати (x, y), інші — через логічні елементи UI. Automator підтримує обидва режими і автоматично перемикається між ними залежно від контексту.

Device Owner API: коли Accessibility недостатньо

Для частини функцій — наприклад, блокування певних застосунків, керування мережею, примусовий показ певного контенту — Accessibility API не дає достатньо прав. Тут вступає Device Owner API.

Це потужний, але складний інструмент. Щоб активувати Device Owner без root, потрібно провести активацію через ADB або спеціальний QR-код при налаштуванні пристрою. Я реалізував повний flow активації прямо з застосунку — з поясненнями кожного кроку, бо звичайний користувач не знає що таке ADB.

Головний виклик тут — безпека. Device Owner має доступ до дуже чутливих операцій. Я витратив значний час на те, щоб переконатися: Automator використовує ці права тільки за прямою командою користувача, ніколи у фоні без підтвердження.

OCR: читаємо те, що не можна прочитати через API

Деякі застосунки — особливо ігри та кастомні UI — повністю ігнорують Accessibility. Їхній контент існує лише як пікселі. Для роботи з ними я інтегрував ML Kit Text Recognition від Google.

OCR в реальному часі — це дорого по ресурсах. Тому я реалізував кілька оптимізацій:

  • Розпізнавання тільки конкретної зони екрану (не весь скріншот)
  • Кешування результатів для статичних елементів
  • Асинхронна черга задач, щоб не блокувати основний потік

Точність виявилась достатньою для більшості задач — але не для всіх. Скручений текст, анімації, низький контраст — все це знижує якість. Довелось додати механізм повторних спроб з різними параметрами попередньої обробки зображення.

On-device AI Agent: без зовнішніх API

Одна з ключових функцій Automator — вбудований AI-агент, який може розуміти задачі на природній мові і виконувати їх автоматично. Наприклад: «Щодня о 9:00 відкрий Telegram, знайди повідомлення від Ірини, скопіюй останнє і відправ мені на пошту».

Принципове рішення: без зовнішніх API. Все працює локально на пристрої. Це означає приватність (дані не залишають телефон), офлайн-роботу та відсутність підписок.

Технічно це реалізовано через TensorFlow Lite з квантизованою моделлю. Звичайно, порівняно з хмарними LLM, локальна модель менш потужна. Але для задач автоматизації — розуміння команд, розбивки на кроки, вибору дій — її цілком достатньо.

Найскладніше тут — планувальник дій. AI генерує план, але хто буде його виконувати? Я розробив власний інтерпретатор макросів: він приймає план від AI у вигляді JSON і транслює його в конкретні команди Accessibility API. Це фактично маленька віртуальна машина всередині застосунку.

Автоматизація: плюси, мінуси і реальність

Що автоматизація дозволяє:

  • Замінити нудну ручну рутину — форми, копіювання, перевірка статусів
  • Запускати складні сценарії по розкладу або тригеру
  • Тестувати застосунки без написання коду (UI testing без Espresso)
  • Доступність — люди з обмеженими можливостями можуть налаштувати застосунок під себе
  • Автоматизація робочих процесів, які не мають API

Реальні обмеження:

  • Android оновлюється — і кожна нова версія може зламати частину логіки. Android 14 і 15 додали нові обмеження на Accessibility Services, довелось адаптуватись
  • Деякі банківські і платіжні застосунки навмисно блокують Accessibility, виявляючи автоматизацію (через FLAG_SECURE і кастомні перевірки)
  • Автоматизація UI крихка — якщо застосунок змінив розташування кнопки, макрос зламається
  • Складні сценарії потребують технічного розуміння від користувача

150 000 рядків: просто про велике

Проєкт ріс органічно — функція за функцією, модуль за модулем. В якийсь момент я озирнувся і побачив 150 тисяч рядків Kotlin. Не страшно, але потребує порядку.

Я не вигадував нічого революційного: кожна велика функція живе у своєму модулі, модулі спілкуються через події а не напряму, а кожне нетривіальне рішення має коментар «чому саме так». Остання звичка рятує найбільше — через пів року забуваєш все.

HTTP-сервер і LAN-передача: застосунок як платформа

Одна з несподіваних функцій, яка стала популярною — вбудований HTTP-сервер. Automator може прийняти запит з браузера або іншого пристрою в мережі і виконати макрос. Це перетворює телефон на IoT-пристрій: можна керувати ним з ПК, інтегрувати в Home Assistant, запускати автоматизації з веб-інтерфейсу.

LAN-передача файлів — простий але корисний інструмент для тих, хто втомився від USB-кабелів і хмарних сховищ.








Гортайте вбік, щоб подивитися всі зображення

Шукаю тестувальників

Застосунок вже доступний у Google Play. Для тестувальників він повністю безкоштовний — Google Play видає безкоштовну ліцензію всім учасникам закритого бета-тестування.

Мені потрібні люди, які:

  • Готові реально користуватись застосунком 14 днів
  • Зацікавлені в автоматизації або accessibility-розробці
  • Можуть залишити чесний відгук — що зручно, що незрозуміло

Якщо цікаво — пишіть у Telegram: @dupikx або в коментарях, надішлю пряме посилання на бета-тест.

Play Store: play.google.com/...​ails?id=com.automator.app

Буду радий технічним питанням у коментарях — особливо про Accessibility API, TFLite на Android і архітектуру великих мобільних застосунків.

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному1
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

[зануда ON]

Це не стаття про те, який я молодець. Це чесна розповідь про те, що таке мобільна автоматизація зсередини, чому це технічно складно, і які рішення я приймав на кожному етапі.

ChatGPT, перелогінься :)
[зануда OFF]

Олександре, дякую за увагу. ChatGPT не писав за мене архітектуру, не налагоджував Accessibility Service і не витрачав місяці на боротьбу з Android 15. За цим проектом — роки платного навчання, щоденна праця і 150 000 рядків коду написаних власноруч. Інструменти — це інструменти, ними користуються всі. Якщо є конкретні технічні питання — із задоволенням відповім. Якщо цікаво протестувати — запрошую в бету.

Так, цілком можливо, що проект класний — я ні в зуб ногою в тому андроїді.
Але ж ви тут не сорс код викладаєте, а статтю. А вона — трохи більше, ніж повністю, згенерована AI, якому сказали написати статтю про проект і дали цей проект.

Ну, можна ж хоча б сказати AI так не писати, а приховати свої стандартні шаблони і оберти, а ще — пройтись по тесту руками після чату :)
Це називається — повага до читача.

Олександре, справедливо. Я програміст, не журналіст — написати 150 000 рядків коду мені значно простіше, ніж статтю. AI допоміг структурувати думки, і я цього не приховую. Але технічний зміст, архітектурні рішення і граблі — мої власні, жоден AI їх за мене не проходив.
Щодо поваги до читача — згоден, це важливо. Але й читач, який одразу пише «ChatGPT, перелогінься» замість технічного питання — теж не зовсім про повагу. Ті, хто дружить з AI як інструментом, заслуговують на таке ж ставлення як і всі інші.

Дякую за статтю!
Цікава ідея для проекту.
Мене цікавить декілька моментів:
Чому ви обрали TensorFlow Lite а не LiteRT (його наступника)?
Модель чи моделі вчили самі з нуля?
Який приблизний інференс?
Який розмір вийшов та яка орієнтовна кількість параметрів моделі?
На чому модель запускається? Тобто на яких обчислювальних модулях працює CPU, GPU, NPU.
Дякую!

Максиме, дякую за увагу до деталей!
Буквально вчора вніс оновлення під Android 15 — і питання дуже своєчасне. Щодо TFLite vs LiteRT: міграція пройшла легко саме завдяки тому, що з початку розробки inference живе в окремому модулі. Змінив залежності, підправив кілька викликів — і все.
Важливе уточнення: в застосунку свідомо немає вбудованої моделі — користувач підключає будь-яку TFLite-модель самостійно. Головна вимога — щоб модель підходила для класифікації намірів або прийняття рішень для автоматизації дій. Це дає гнучкість: хто хоче легкість — бере маленьку квантизовану модель, хто хоче точність — підключає важчу.
Інференс на середньому сучасному пристрої — 80-150мс. Запускається на CPU з GPU-делегатом де підтримується. NPU поки свідомо не використовую — занадто різниться між виробниками.
Якщо є ще питання — радий відповісти!

Цікаво, а чи є якісь рекомендовані моделі «з коробки» для користувачів, які не дуже знайомі з локальними AI-моделями? Чи зараз передбачається, що користувач сам обирає та підключає модель?

Максиме, справедливе зауваження — зараз користувач підключає модель самостійно.

Щодо рекомендацій: найкраще брати найновішу модель у своїй лінійці, але під кожну задачу підходить своя:
— MobileBERT — якщо потрібна швидка класифікація намірів, легкий і шустрий (~25 МБ)
— DistilBERT TFLite — якщо важливіша точність і розмір не критичний
— Будь-яка кастомна модель, натренована на intent detection датасетах (SNIPS, ATIS) — якщо є специфічні сценарії автоматизації

Загальний принцип: чим простіша задача — тим менша модель впорається, і тим швидший інференс.

До речі — якщо цікаво протестувати це на практиці, запрошую в бета-тест. Кинь мені свій Gmail в особисті, додам до закритого тестування 🙌

Цікаво.
Можемо один одному допомогти).
Я краз випустив новий функціонал для свого додатку який має у собі ML та CV.
play.google.com/...​ions.morsecodeinterpreter
Ок, email скину в особисті

Підписатись на коментарі