Настройка ProGuard/R8 mapping загрузки для деобфускации крашей Android

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Настройка ProGuard/R8 mapping загрузки для деобфускации крашей Android
Средняя
от 4 часов до 2 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    761
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    649
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1071
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    884
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    466

Настройка ProGuard/R8 mapping загрузки для деобфускации крашей Android

Firebase Crashlytics показывает a.b.c.d.e(Unknown Source:12) вместо com.example.app.checkout.PaymentViewModel.processPayment(PaymentViewModel.kt:89). ProGuard и R8 переименовывают классы и методы в минимизированных production-сборках — без mapping-файла стектрейс нечитаем. Проблема возникает не только у новых проектов: часто mapping перестаёт загружаться после смены CI или обновления AGP.

Где ломается деобфускация

Mapping не загружается автоматически на CI. Плагин com.google.firebase.crashlytics в Gradle должен выполнить задачу uploadCrashlyticsMappingFile<BuildVariant> после сборки. На чистом CI-агенте задача выполняется, но если google-services.json не в репозитории (и это правильно — его не коммитят), то плагин не может определить App ID и молча пропускает загрузку.

R8 и legacy ProGuard дают разные mapping-форматы. AGP 7.0+ использует R8 по умолчанию. Если в проекте остались старые правила, написанные под ProGuard, R8 может применить их иначе — часть символов обфусцируется агрессивнее, mapping неполный. Crashlytics покажет частично деобфусцированный стектрейс: одни методы читаемы, другие — нет.

Многомодульные проекты. В проекте с 10+ модулями R8 в fullMode (включён по умолчанию в AGP 8.x) работает через весь граф зависимостей. Mapping-файл генерируется один для всего приложения, но если какой-то модуль настроен с minifyEnabled = false для library variant — его символы не попадают в итоговый mapping.

Как настроить корректную загрузку

Gradle-конфигурация

// app/build.gradle.kts
android {
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

// Crashlytics mapping upload
firebaseCrashlytics {
    mappingFileUploadEnabled = true
    nativeSymbolUploadEnabled = false // только для NDK-крашей
}

mappingFileUploadEnabled = true — явно указываем, не полагаясь на дефолт. После AGP 8.x дефолт — true для release, но лучше задать явно.

Передача google-services.json на CI

google-services.json не должен быть в репозитории. На CI передаём через переменную окружения:

# GitHub Actions
- name: Decode google-services.json
  env:
    GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
  run: echo "$GOOGLE_SERVICES_JSON" | base64 --decode > app/google-services.json

- name: Build and upload mapping
  run: ./gradlew assembleRelease uploadCrashlyticsMappingFileRelease

Задача uploadCrashlyticsMappingFileRelease запускается отдельно — это важно, потому что при assembleRelease плагин иногда завершает upload асинхронно и CI не ждёт результата.

Ручная загрузка через Firebase CLI

Если автоматическая загрузка по какой-то причине не подходит:

firebase crashlytics:mappingfile:upload \
  --app=1:123456789:android:abcdef \
  app/build/outputs/mapping/release/mapping.txt

Mapping-файл всегда находится в app/build/outputs/mapping/<buildType>/mapping.txt. Сохраняйте его как артефакт CI — без него деобфускация старых крашей невозможна после смены версии кода.

Хранение mapping-файлов

Правило: каждый production-релиз → архивируем mapping.txt с пометкой версии и build number. Через 6 месяцев пользователи всё ещё могут запускать старые версии приложения, и крэши с них придут без символов, если mapping потерян.

# В CI: сохранить как артефакт
cp app/build/outputs/mapping/release/mapping.txt \
   artifacts/mapping-${VERSION_NAME}-${VERSION_CODE}.txt

Проверка через Retrace

Для локальной верификации:

# Android SDK tools
retrace.sh \
  app/build/outputs/mapping/release/mapping.txt \
  obfuscated-stacktrace.txt

Если retrace восстанавливает читаемый стектрейс локально, но Crashlytics всё равно показывает обфусцированный — mapping не был загружен. Проверяем в Firebase Console: Crashlytics → App → три точки → Mapping Files.

R8 fullMode и сохранение нужных символов

В AGP 8.x R8 fullMode включён по умолчанию и удаляет символы агрессивнее. Для Retrofit, Gson, Room нужны явные keep-правила:

# proguard-rules.pro
-keepattributes SourceFile,LineNumberTable
-keep class com.example.app.data.model.** { *; }
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName <fields>;
}

-keepattributes SourceFile,LineNumberTable — без этого mapping есть, но номера строк в стектрейсе будут неверными.

Ориентиры по срокам

Настройка для стандартного проекта с CI на GitHub Actions — 3–6 часов. Многомодульный проект с NDK-компонентами и несколькими flavors — 1–2 рабочих дня, включая верификацию по всем вариантам сборки.