Налаштування завантаження 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
    763
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    649
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1073
  • 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 робочих дні, включаючи верифікацію за всіма варіантами збірки.