← назад к разделу

Оплата проверена вдоль и поперёк: карта, промокод, чек. У пользователя посреди ввода карты звонит телефон. Через минуту он возвращается — корзина пуста, промокод слетел, приложение открылось с главного экрана. Функция работает, оплаты нет.

Телефон отличается от браузера не размером экрана — про вёрстку и наборы экранов есть отдельная статья. Здесь про другое: экраном, памятью, сетью и доступом к камере на телефоне распоряжается система, и она в любой момент отодвигает приложение в сторону или выгружает совсем.

экран оформления заказа: что лежит в памяти на каждом шаге 1 · открыткорзина: 3 штпромокод введёншаг 2 из 3таймер брони идёт 2 · свёрнутзвонок, шторкапроцесс ещё живэкран не виденвидео и звук? 3 · вернулисьпроцесс жив —всё на местебронь не истекла?двойной запрос? 4 · выгруженмало памятипроцесс убитполя пустыстроится заново пользователь не знает, что процесс убивали:он вернулся в приложение и увидел пустую форму

Четвёртый шаг — не редкость, а обычное поведение системы при нехватке памяти. Если приложение не сохранило состояние экрана, возврат из фона выглядит как сброс: введённое пропало, шаг формы забыт, а таймер брони мог тем временем истечь. Для пользователя все четыре шага — одно действие: «свернул и вернулся».

Нативное, гибридное, веб и PWA

«Мобильное приложение» — четыре разные вещи, и от того, какая перед вами, зависит, где искать причину.

Нативное написано под одну систему (Kotlin или Java для Android, Swift для iOS) и ставится из магазина. Гибридное — веб-страница внутри окна-обёртки: кнопки выглядят родными, а нарисованы HTML и CSS, поэтому половина дефектов тут веб-дефекты, а половина — на стыке обёртки с камерой и уведомлениями. Мобильный сайт живёт в браузере телефона и обновляется мгновенно. PWA — тот же сайт на домашнем экране: свой значок, запуск без адресной строки, часть данных доступна без сети.

Для проверок разница в трёх вещах: как доезжает новая версия (магазин с проверкой и раскаткой — или обновление страницы у всех сразу), где логи (журнал системы — или консоль браузера), что доступно из системы (камера, отпечаток, уведомления, файлы — у веб-версии набор урезан).

Прерывания: то, что проверяют первым

Звонок, будильник, уведомление, кнопка «домой», карта поверх — экран уходит в фон и через минуту возвращается. Иногда не тем же: системе не хватило памяти, и фоновый процесс она выгрузила.

Проверяют это первым, потому что ломается почти всё: черновик, таймер брони, видео, играющее поверх звонка, платёж, ушедший вторым запросом.

Набор одинаков для любого приложения: свернуть на середине формы и вернуться; принять звонок; открыть шторку; повернуть экран; заблокировать и разблокировать; закрыть приложение из списка задач и открыть заново.

Ждать выгрузку бессмысленно: в меню разработчика Android есть переключатель «Не сохранять действия» (Don't keep activities) — система убивает экран сразу, как он ушёл в фон, и потеря состояния находится за минуту.

Сеть: переключения и офлайн

На стенде Wi-Fi ровный, у пользователя — метро, лифт и переход с домашнего Wi-Fi на мобильную сеть у подъезда. Сеть на телефоне не делится на «есть» и «нет»: она бывает медленной и обрывается посреди загрузки.

Что проверяют: авиарежим на середине отправки — приложение говорит, что связи нет, не показывает пустой экран и не теряет введённое; вернуть сеть — данные догружаются сами или по кнопке, без перезахода; переключить Wi-Fi на мобильную сеть прямо во время запроса; открыть приложение на медленном канале — профили скорости есть в эмуляторе и в DevTools.

Главная ловушка — повтор: запрос ушёл, сервер его выполнил, ответ не доехал, приложение отправило ещё раз — и появился второй заказ. Проверка: оборвать сеть сразу после «Оплатить», вернуть и посмотреть, сколько заказов и списаний получилось.

Разрешения: выдали, отказали, отозвали

Камеру, геолокацию, уведомления, контакты и файлы приложение получает у системы, и пользователь в любой момент может передумать. Состояний три, проверяют обычно одно.

Выдали — обычный путь. Отказали — приложение обязано остаться рабочим: объяснить, зачем нужно разрешение, и оставить обходной путь (адрес руками вместо геолокации). Отозвали позже, в настройках системы, — самый ломкий случай: Android при отзыве убивает процесс, и приложение стартует заново. Отдельно проверяют «отказать и больше не спрашивать»: системный диалог не появится никогда, и вести в настройки приложение должно само.

Установка, обновление и версия

Чистая установка и обновление поверх — два разных сценария, и ломается обычно второй: у пользователя уже лежат данные прошлой версии, вход и кэш, и новая сборка должна их пережить.

Порядок: поставить прошлую версию, войти, создать данные, обновиться на новую сборку. Вход остался, данные открылись, экраны не падают.

У сборки два номера: тот, что видит пользователь (3.4.1), и внутренний, растущий с каждой сборкой. В дефект пишут оба плюс модель телефона и версию системы, иначе воспроизвести нечем. Магазин отдаёт версию не всем сразу: «у меня обновилось, у тебя нет» — норма, а не дефект.

Глубокие ссылки и уведомления

Глубокая ссылка открывает не главный экран, а конкретный: письмо про заказ — сразу к заказу. Проверяют в трёх состояниях: открыто, свёрнуто, закрыто. Ломается чаще всего третье — приложение стартует с нуля и теряет ссылку по дороге. Ещё два: пользователь не вошёл (после входа должен попасть на нужный экран, а не на главную) и объект удалён (понятное сообщение вместо пустоты).

С уведомлениями состояния те же три: открыто — уведомление не перекрывает работу; свёрнуто — приходит в шторку; закрыто — тап поднимает приложение и открывает нужный экран. Плюс мелочи: обрезка длинного текста, несколько уведомлений подряд, счётчик на значке, выключенные уведомления в настройках.

На чём проверять: устройства, эмуляторы, фермы

Моделей телефонов тысячи, версий системы — десятки, и поверх идут оболочки производителей, которые экономят батарею и убивают фоновые задачи по-своему. Набор собирают по статистике аудитории; обычно хватает четырёх-пяти устройств: самая массовая модель, самая старая поддерживаемая версия системы, самый маленький экран, один iPhone и один Android.

Эмулятор Android запускает настоящий образ системы на компьютере. Симулятор iOS — не телефон, а сборка приложения под macOS: память и скорость там свои, часть возможностей недоступна. Ни тот ни другой не дадут реальную камеру, отпечаток, слабый процессор, разряд батареи и настоящую мобильную сеть. Поэтому экраны гоняют на эмуляторе, а деньги, камеру, сеть и прерывания — на живом устройстве. Нет нужной модели — берут облачную ферму: настоящие телефоны в аренду по минутам, с удалённым экраном и логами.

Где смотреть логи

«Упало» без логов — не дефект, а сообщение о невезении. На Android журнал читают через adb: adb devices покажет подключённый телефон, adb logcat — поток системного журнала (в Android Studio это вкладка LogCat с фильтром по приложению), adb install app.apk поставит сборку, adb shell pm clear <пакет> сотрёт данные до состояния чистой установки. На iOS то же смотрят в Console на Mac или в окне устройств Xcode. Стек падения в баг-репорте экономит разработчику день поисков.

Коротко

  • Приложением на телефоне распоряжается система: сворачивает, выгружает, отбирает разрешения.
  • Прерывания проверяют первыми; выгрузку воспроизводит переключатель «Не сохранять действия» в меню разработчика Android.
  • Сеть переключается и пропадает посреди запроса; главная ловушка — повтор, создающий второй заказ.
  • У разрешения три состояния: выдали, отказали, отозвали позже — при отзыве Android перезапускает приложение.
  • Обновление поверх — отдельный сценарий: данные, вход и кэш должны пережить новую сборку.
  • Эмулятор и симулятор годятся для экранов; деньги, камеру, сеть и прерывания — на живом устройстве или в ферме.

Что почитать дальше