Получайте отчеты о сбоях Android NDK

Если ваше приложение Android содержит собственные библиотеки , вы можете включить полную трассировку стека и подробные отчеты о сбоях для вашего собственного кода из Firebase Crashlytics внеся несколько небольших обновлений в конфигурацию сборки вашего приложения.

В этом руководстве описывается, как настроить отчеты о сбоях с помощью Firebase Crashlytics SDK для NDK.

Если вы ищете, как начать использовать Crashlytics в своих проектах Unity, ознакомьтесь с руководством по началу работы с Unity .

Прежде чем начать

  1. Если вы еще этого не сделали, добавьте Firebase в свой проект Android. Если у вас нет приложения для Android, вы можете загрузить его образец .

  2. Рекомендуется : чтобы автоматически получать навигационные журналы для понимания действий пользователя, приведших к сбою, нефатальному событию или событию ANR, вам необходимо включить Google Analytics в своем проекте Firebase.

    • Если в вашем существующем проекте Firebase не включен Google Analytics , вы можете включить Google Analytics на вкладке «Интеграции» вашего аккаунта. > Настройки проекта в консоли Firebase .

    • Если вы создаете новый проект Firebase, включите Google Analytics во время рабочего процесса создания проекта.

  3. Убедитесь, что ваше приложение имеет следующие минимальные необходимые версии:

    • Градл 8.0
    • Плагин Android Gradle 8.1.0
    • Плагин Gradle сервисов Google 4.4.1

Шаг 1. Добавьте Crashlytics SDK для NDK в свое приложение.

В файле Gradle вашего модуля (на уровне приложения) (обычно <project>/<app-module>/build.gradle.kts или <project>/<app-module>/build.gradle ) добавьте зависимость для библиотеки Crashlytics NDK для Android. Мы рекомендуем использовать Firebase Android BoM для управления версиями библиотеки.

Для оптимальной работы с Crashlytics мы рекомендуем включить Google Analytics в вашем проекте Firebase и добавить Firebase SDK для Google Analytics в ваше приложение.

dependencies {
    // Import the BoM for the Firebase platform
    implementation(platform("com.google.firebase:firebase-bom:33.9.0"))

    // Add the dependencies for the Crashlytics NDK and Analytics libraries
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-crashlytics-ndk")
    implementation("com.google.firebase:firebase-analytics")
}

Используя Firebase Android BoM , ваше приложение всегда будет использовать совместимые версии библиотек Firebase Android.

Если вы решите не использовать Firebase BoM , вы должны указать каждую версию библиотеки Firebase в ее строке зависимости.

Обратите внимание: если вы используете в своем приложении несколько библиотек Firebase, мы настоятельно рекомендуем использовать BoM для управления версиями библиотек, что гарантирует совместимость всех версий.

dependencies {
    // Add the dependencies for the Crashlytics NDK and Analytics libraries
    // When NOT using the BoM, you must specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-crashlytics-ndk:19.4.0")
    implementation("com.google.firebase:firebase-analytics:22.2.0")
}
Ищете библиотечный модуль, специфичный для Kotlin? Начиная с октября 2023 года ( Firebase BoM 32.5.0) от основного модуля библиотеки могут зависеть как разработчики Kotlin, так и Java (подробнее см. FAQ по этой инициативе ).

Шаг 2. Добавьте плагин Crashlytics Gradle в свое приложение.

  1. В файле Gradle корневого уровня (уровня проекта) ( <project>/build.gradle.kts или <project>/build.gradle ) добавьте плагин Crashlytics Gradle в блок plugins :

    KotlinGroovy
    plugins {
        // Make sure that you have the AGP plugin 8.1+ dependency
        id("com.android.application") version "8.1.4" apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
        id("com.google.gms.google-services") version "4.4.2" apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id("com.google.firebase.crashlytics") version "3.0.3" apply false
    }
    plugins {
        // Make sure that you have the AGP plugin 8.1+ dependency
        id 'com.android.application' version '8.1.4' apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
        id 'com.google.gms.google-services' version '4.4.2' apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id 'com.google.firebase.crashlytics' version '3.0.3' apply false
    }
  2. В файле Gradle вашего модуля (на уровне приложения) (обычно <project>/<app-module>/build.gradle.kts или <project>/<app-module>/build.gradle ) добавьте плагин Crashlytics Gradle:

    KotlinGroovy
    plugins {
      id("com.android.application")
      // ...
    
      // Make sure that you have the Google services Gradle plugin
      id("com.google.gms.google-services")
    
      // Add the Crashlytics Gradle plugin
      id("com.google.firebase.crashlytics")
    }
    plugins {
      id 'com.android.application'
      // ...
    
      // Make sure that you have the Google services Gradle plugin
      id 'com.google.gms.google-services'
    
      // Add the Crashlytics Gradle plugin
      id 'com.google.firebase.crashlytics'
    }

Шаг 3. Добавьте расширение Crashlytics в свою сборку.

В файле Gradle вашего модуля (на уровне приложения) (обычно <project>/<app-module>/build.gradle.kts или <project>/<app-module>/build.gradle ) настройте расширение Crashlytics.

KotlinGroovy
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension

// ...

android {
  // ...
  buildTypes {
      getByName("release") {
          // Add this extension
          configure<CrashlyticsExtension> {
              // Enable processing and uploading of native symbols to Firebase servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled = true
          }
      }
  }
}
// ...

android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Firebase servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled true
          }
      }
  }
}

Шаг 4. Настройте автоматическую загрузку собственных символов.

Чтобы создавать читаемые трассировки стека при сбоях NDK, Crashlytics необходимо знать о символах в ваших собственных двоичных файлах. Плагин Crashlytics Gradle включает задачу uploadCrashlyticsSymbolFile BUILD_VARIANT для автоматизации этого процесса.

  1. Чтобы вы могли получить доступ к задаче автоматической загрузки символов, убедитесь, что для nativeSymbolUploadEnabled установлено значение true в файле Gradle вашего модуля (на уровне приложения).

  2. Чтобы имена методов появлялись в трассировках стека, вы должны явно вызывать задачу uploadCrashlyticsSymbolFile BUILD_VARIANT после каждой сборки вашей библиотеки NDK. Например:

    >./gradlew app:assembleBUILD_VARIANT\
               app:uploadCrashlyticsSymbolFileBUILD_VARIANT
  3. И Crashlytics SDK для NDK, и плагин Crashlytics Gradle зависят от наличия идентификатора сборки GNU в собственных общих объектах.

    Вы можете проверить наличие этого идентификатора, запустив readelf -n для каждого двоичного файла. Если идентификатор сборки отсутствует, добавьте -Wl,--build-id к флагам вашей системы сборки, чтобы устранить проблему.

Шаг 5. Принудительно завершите тест для завершения настройки.

Чтобы завершить настройку Crashlytics и просмотреть исходные данные на панели управления Crashlytics консоли Firebase , необходимо принудительно завершить тест.

  1. Добавьте в свое приложение код, который можно использовать для принудительного завершения теста.

    Вы можете использовать следующий код в MainActivity вашего приложения, чтобы добавить в приложение кнопку, нажатие которой вызывает сбой. Кнопка называется «Тестовый сбой».

    KotlinJava
    val crashButton = Button(this)
    crashButton.text = "Test Crash"
    crashButton.setOnClickListener {
       throw RuntimeException("Test Crash") // Force a crash
    }
    
    addContentView(crashButton, ViewGroup.LayoutParams(
           ViewGroup.LayoutParams.MATCH_PARENT,
           ViewGroup.LayoutParams.WRAP_CONTENT))
    Button crashButton = new Button(this);
    crashButton.setText("Test Crash");
    crashButton.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           throw new RuntimeException("Test Crash"); // Force a crash
       }
    });
    
    addContentView(crashButton, new ViewGroup.LayoutParams(
           ViewGroup.LayoutParams.MATCH_PARENT,
           ViewGroup.LayoutParams.WRAP_CONTENT));
  2. Создайте и запустите свое приложение.

  3. Принудительно завершить тест, чтобы отправить первый отчет о сбое вашего приложения:

    1. Откройте приложение на тестовом устройстве или в эмуляторе.

    2. В своем приложении нажмите кнопку «Тестировать сбой», которую вы добавили с помощью приведенного выше кода.

    3. После сбоя вашего приложения перезапустите его, чтобы ваше приложение могло отправить отчет о сбое в Firebase.

  4. Перейдите на панель управления Crashlytics консоли Firebase , чтобы увидеть сбой вашего теста.

    Если вы обновили консоль и по-прежнему не видите сбой теста через пять минут, включите ведение журнала отладки, чтобы узнать, отправляет ли ваше приложение отчеты о сбоях.


И все! Crashlytics теперь отслеживает ваше приложение на предмет сбоев, и вы можете просматривать и исследовать отчеты о сбоях и статистику на панели управления Crashlytics .

Следующие шаги

  • (Рекомендуется) Получите помощь в устранении сбоев, вызванных ошибками собственной памяти, собрав отчеты GWP-ASan . Эти ошибки, связанные с памятью, могут быть связаны с повреждением памяти вашего приложения, что является основной причиной уязвимостей безопасности приложений. Чтобы воспользоваться этой функцией отладки, убедитесь, что в вашем приложении явно включен GWP-ASan и используется последняя версия Crashlytics SDK для NDK (v18.3.6+ или Firebase BoM v31.3.0+).

  • Настройте настройку отчета о сбоях, добавив дополнительные отчеты, журналы, ключи и отслеживание нефатальных ошибок.

  • Интегрируйтесь с Google Play , чтобы можно было фильтровать отчеты о сбоях вашего приложения Android по трекам Google Play прямо на панели управления Crashlytics . Это позволяет вам лучше сосредоточить панель управления на конкретных сборках.

Поиск неисправностей

Если вы видите разные трассировки стека в консоли Firebase и в logcat, обратитесь к руководству по устранению неполадок .



Альтернативные варианты загрузки символов

Основной рабочий процесс на этой странице выше применим для стандартных сборок Gradle. Однако некоторые приложения используют другую конфигурацию или инструменты (например, процесс сборки, отличный от Gradle). В таких ситуациях для успешной загрузки символов могут быть полезны следующие параметры.

Опция : загрузить символы для библиотечных модулей и внешних зависимостей.

Эта опция может быть полезна в следующих ситуациях:

  • Если вы используете настраиваемый процесс сборки NDK в Gradle
  • Если ваши собственные библиотеки встроены в библиотечный/функциональный модуль или предоставлены сторонними
  • Если задача автоматической загрузки символов не удалась или вы видите бессимволические сбои на панели управления.

Стандартная задача загрузки символов Crashlytics предполагает, что вы создаете собственные библиотеки как часть сборки Gradle вашего модуля приложения, используя стандартные инструменты сборки NDK, такие как CMake.

Однако, если вы используете настраиваемый процесс сборки NDK в Gradle или ваши собственные библиотеки встроены в библиотечный/функциональный модуль или предоставлены третьей стороной, вам может потребоваться явно указать путь к вашим нераспакованным библиотекам. Для этого вы можете добавить свойство unstrippedNativeLibsDir в расширение Crashlytics в файле сборки Gradle.

  1. Убедитесь, что вы выполнили следующие первоначальные задачи основного рабочего процесса ранее на этой странице:

    1. Включил Crashlytics в консоли Firebase .

    2. Добавлен Crashlytics SDK для NDK и плагин Crashlytics Gradle .

    3. В вашу сборку добавлено расширение Crashlytics.

    4. Настройте автоматическую загрузку нативных символов.

  2. Чтобы задача автоматической загрузки символов могла найти информацию о вашем символе, добавьте следующее в файл Gradle вашего модуля (на уровне приложения) (обычно <project>/<app-module>/build.gradle.kts или <project>/<app-module>/build.gradle ):

    KotlinGroovy
    import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
    
    // ...
    
    android {
        // ...
        buildTypes {
            release {
                configure<CrashlyticsExtension> {
                    nativeSymbolUploadEnabled = true
                    unstrippedNativeLibsDir = file("PATH/TO/UNSTRIPPED/DIRECTORY")
                }
            }
        }
    }
    // ...
    
    android {
        // ...
        buildTypes {
            release {
                firebaseCrashlytics {
                    nativeSymbolUploadEnabled true
                    unstrippedNativeLibsDir file("PATH/TO/UNSTRIPPED/DIRECTORY")
                }
            }
        }
    }

    Плагин Crashlytics будет рекурсивно искать в указанном каталоге собственные библиотеки с расширением .so . Затем Crashlytics извлекает символы отладки из всех таких библиотек и загружает их на серверы Firebase.

    Вот что вы можете указать в свойстве unstrippedNativeLibsDir :

    • Любой аргумент, допустимый для org.gradle.api.Project#files(Object...) , включая: java.lang.String , java.io.File или org.gradle.api.file.FileCollection

    • Несколько каталогов для одного варианта сборки путем предоставления списка или экземпляра FileCollection

    • (Начиная с плагина Crashlytics Gradle v3.0.0) Собирайте несколько каталогов в отдельных продуктах и ​​создавайте варианты.

      buildTypes {
        release {
          configure<CrashlyticsExtension> {
            nativeSymbolUploadEnabled = true
            unstrippedNativeLibsDir = file("MY/NATIVE/LIBS")
          }
        }
        productFlavors {
          flavorDimensions += "feature"
          create("basic") {
            dimension = "feature"
            // ...
          }
          create("featureX") {
            dimension = "feature"
            configure<CrashlyticsExtension> {
              unstrippedNativeLibsDir = file("MY/FEATURE_X/LIBS")
            }
          }
        }
      }
      

    Задача uploadCrashlyticsSymbolFilesBasicRelease загрузит символы только в MY/NATIVE/LIBS , а uploadCrashlyticsSymbolFilesFeatureXRelease загрузит символы как в MY/NATIVE/LIBS так и MY/FEATURE_X/LIBS .

  3. Наконец, принудительно завершите тест , чтобы завершить настройку Crashlytics и просмотреть исходные данные на панели управления Crashlytics консоли Firebase .

Вариант : загрузить символы для сборок, отличных от Gradle, или недоступных нераспакованных собственных библиотек.

Эта опция может быть полезна в следующих ситуациях:

  • Если вы используете процесс сборки, отличный от Gradle

  • Если ваши нераспакованные собственные библиотеки предоставляются вам таким образом, что они недоступны во время сборок Gradle

Этот параметр требует, чтобы вы запускали команду Firebase CLI при создании сборки выпуска или любой сборки, для которой вы хотите видеть символизированные трассировки стека в консоли Firebase .

  1. Убедитесь, что вы выполнили следующие первоначальные задачи основного рабочего процесса ранее на этой странице:

    1. Включил Crashlytics в консоли Firebase .

    2. Добавлен Crashlytics SDK для NDK и плагин Crashlytics Gradle .

    Обратите внимание, что при использовании этого параметра вам не нужно добавлять расширение firebaseCrashlytics или настраивать автоматическую загрузку символов, поскольку вместо этого вы будете использовать интерфейс командной строки Firebase (следующие шаги ниже) для создания и загрузки файлов символов.

  2. Настройте среду и проект для загрузки символов:

    1. Следуйте инструкциям по установке Firebase CLI .

      Если вы уже установили CLI, обязательно обновите его до последней версии .

    2. (только для приложений, использующих Android API уровня 30+) Обновите шаблон AndroidManifest.xml вашего приложения, чтобы отключить тегирование указателем:

      1. Установите флажок «Настройки Android Player» > «Настройки публикации» > «Сборка» > «Пользовательский основной манифест» .

      2. Откройте шаблон манифеста, расположенный в Assets/Plugins/Android/AndroidManifest.xml .

      3. Добавьте в тег приложения следующий атрибут: <application android:allowNativeHeapPointerTagging="false" ... />

  3. Создайте свой проект.

  4. Загрузите информацию о своих символах.

    После завершения сборки создайте файл символов, совместимый с Crashlytics , и загрузите его на серверы Firebase, выполнив следующую команду Firebase CLI:

    firebase crashlytics:symbols:upload --app=FIREBASE_APP_ID PATH/TO/SYMBOLS
    • FIREBASE_APP_ID : идентификатор вашего приложения Firebase для Android (а не имя вашего пакета).
      Пример идентификатора приложения Firebase для Android: 1:567383003300:android:17104a2ced0c9b9b

      Вот два способа найти идентификатор приложения Firebase:

      • В файле google-services.json вашим идентификатором приложения является значение mobilesdk_app_id ; или

      • В консоли Firebase перейдите в настройки проекта . Прокрутите вниз до карточки «Ваши приложения» , затем нажмите нужное приложение Firebase, чтобы найти его идентификатор приложения.

    • PATH/TO/SYMBOLS : путь к файлу символов, созданному CLI.

      • Экспортируется в проект Android Studio — PATH/TO/SYMBOLS может быть любым каталогом. Интерфейс командной строки Firebase будет рекурсивно искать в указанном каталоге собственные библиотеки с расширением .so .

      • Создан APK непосредственно из Unity. PATH/TO/SYMBOLS — это путь к сжатому файлу символов, созданному в корневом каталоге проекта после завершения сборки (например: myproject/myapp-1.0-v100.symbols.zip ).

    Флаг Описание
    --generator=csym

    Использует устаревший генератор файлов символов cSYM вместо генератора Breakpad по умолчанию.

    Не рекомендуется к использованию. Мы рекомендуем использовать генератор файлов символов Breakpad по умолчанию.

    --generator=breakpad

    Использует генератор файлов символов Breakpad.

    Обратите внимание, что по умолчанию для создания файла символов используется Breakpad. Используйте этот флаг, только если вы добавили symbolGenerator { csym() } в вашей конфигурации сборки, и вы хотите переопределить его, чтобы вместо этого использовать Breakpad.

    --dry-run

    Создает файлы символов, но не загружает их.

    Этот флаг полезен, если вы хотите проверить содержимое отправляемых файлов.

    --debug Предоставляет дополнительную информацию для отладки.
  5. Наконец, принудительно завершите тест , чтобы завершить настройку Crashlytics и просмотреть исходные данные на панели управления Crashlytics консоли Firebase .

    После того, как вы создадите свое приложение в рамках принудительного сбоя, обязательно запустите команду Firebase CLI crashlytics:symbols:upload , чтобы загрузить файл символов.