Google은 흑인 공동체를 위한 인종적 평등을 추구하기 위해 노력하고 있습니다. 자세히 알아보기

Android NDK 비정상 종료 보고서 받기

Android 앱에 네이티브 라이브러리가 포함되어 있는 경우 Firebase Crashlytics에서 앱의 빌드 구성을 소규모 업데이트하여 네이티브 코드에 대한 전체 스택 트레이스와 상세한 비정상 종료 보고서를 사용할 수 있습니다. 이 가이드에서는 새 Firebase Crashlytics SDK를 사용하여 비정상 종료 보고를 구성하는 방법을 설명합니다.

시작하기 전에

시작하려면 Crashlytics를 설정합니다.

  1. 2단계(앱에 Firebase Crashlytics 플러그인 추가) 진행 중에 앱에서 Crashlytics Gradle 플러그인 v2.4.0 이상을 사용하는지 확인합니다. 이 플러그인을 사용하면 기호화된 장애를 일으키기 위해 삭제되지 않은 바이너리만 사용하여 기호를 업로드할 수 있습니다.

1단계: Gradle 구성 업데이트

앱 수준 build.gradle에서 Crashlytics NDK 런타임 종속 항목을 선언합니다.

자바

apply plugin: 'com.android.application'
apply plugin: 'com.google.firebase.crashlytics'

dependencies {
  // ...

  // Import the BoM for the Firebase platform
  implementation platform('com.google.firebase:firebase-bom:28.4.0')

  // Declare the dependency for the Firebase Crashlytics NDK library.
  // If you previously declared the Firebase Crashlytics dependency, replace it.
  // When using the BoM, you don't specify versions in Firebase library dependencies
  implementation 'com.google.firebase:firebase-crashlytics'
  implementation 'com.google.firebase:firebase-crashlytics-ndk'
  implementation 'com.google.firebase:firebase-analytics'
}

// …
android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Crashlytics 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
          }
      }
  }
}

Firebase Android BoM을 사용하면 앱에서 항상 호환되는 Firebase Android 라이브러리 버전을 사용합니다.

(대안) BoM을 사용하지 않고 Firebase 라이브러리 종속 항목을 선언합니다.

Firebase BoM을 사용하지 않도록 선택한 경우에는 종속 항목 줄에 각 Firebase 라이브러리 버전을 지정해야 합니다.

앱에서 여러 Firebase 라이브러리를 사용하는 경우 모든 버전이 호환되도록 BoM을 사용하여 라이브러리 버전을 관리하는 것이 좋습니다.

  dependencies {
      // Declare the dependency for the Firebase Crashlytics NDK library.
      // If you previously declared the Firebase Crashlytics dependency, replace it.
      // When NOT using the BoM, you must specify versions in Firebase library dependencies
      implementation 'com.google.firebase:firebase-crashlytics:18.2.1'
      implementation 'com.google.firebase:firebase-crashlytics-ndk:18.2.1'
      implementation 'com.google.firebase:firebase-analytics:19.0.1'
  }
  

Kotlin+KTX

apply plugin: 'com.android.application'
apply plugin: 'com.google.firebase.crashlytics'

dependencies {
  // ...

  // Import the BoM for the Firebase platform
  implementation platform('com.google.firebase:firebase-bom:28.4.0')

  // Declare the dependency for the Firebase Crashlytics NDK library.
  // If you previously declared the Firebase Crashlytics dependency, replace it.
  // When using the BoM, you don't specify versions in Firebase library dependencies
  implementation 'com.google.firebase:firebase-crashlytics-ktx'
  implementation 'com.google.firebase:firebase-crashlytics-ndk'
  implementation 'com.google.firebase:firebase-analytics-ktx'
}

// …
android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Crashlytics 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
          }
      }
  }
}

Firebase Android BoM을 사용하면 앱에서 항상 호환되는 Firebase Android 라이브러리 버전을 사용합니다.

(대안) BoM을 사용하지 않고 Firebase 라이브러리 종속 항목을 선언합니다.

Firebase BoM을 사용하지 않도록 선택한 경우에는 종속 항목 줄에 각 Firebase 라이브러리 버전을 지정해야 합니다.

앱에서 여러 Firebase 라이브러리를 사용하는 경우 모든 버전이 호환되도록 BoM을 사용하여 라이브러리 버전을 관리하는 것이 좋습니다.

  dependencies {
      // Declare the dependency for the Firebase Crashlytics NDK library.
      // If you previously declared the Firebase Crashlytics dependency, replace it.
      // When NOT using the BoM, you must specify versions in Firebase library dependencies
      implementation 'com.google.firebase:firebase-crashlytics-ktx:18.2.1'
      implementation 'com.google.firebase:firebase-crashlytics-ndk:18.2.1'
      implementation 'com.google.firebase:firebase-analytics-ktx:19.0.1'
  }
  

Crashlytics NDK 버전 17.3.0에 필수: 앱에서 targetSdkLevel 30 이상을 사용하는 경우 AndroidManifest.xml에 다음을 추가하여 앱에서 포인터 태그 기능도 사용 중지해야 합니다.

<application android:allowNativeHeapPointerTagging="false">
...
</application>

자세한 내용은 태그된 포인터에 대한 개발자 지원을 참조하세요.

2단계: 네이티브 기호 업로드 사용 설정

NDK 비정상 종료로부터 읽기 가능한 스택 트레이스를 생성하려면 Crashlytics에서 네이티브 바이너리의 기호에 대해 파악해야 합니다. Gradle 플러그인에는 이 과정을 자동화하는 uploadCrashlyticsSymbolFileBUILD_VARIANT 태스크가 포함되어 있습니다. 이 태스크에 액세스하려면 nativeSymbolUploadEnabled가 true로 설정되었는지 확인합니다.

스택 트레이스에 나타나는 메서드 이름의 경우 NDK 라이브러리를 빌드할 때마다 uploadCrashlyticsSymbolFileBUILD_VARIANT 태스크를 명시적으로 호출해야 합니다. 예를 들면 다음과 같습니다.

>./gradlew app:assembleBUILD_VARIANT\
           app:uploadCrashlyticsSymbolFileBUILD_VARIANT

Crashlytics NDK v17.3.0 이상 및 Gradle 플러그인 v2.4.1 이상의 경우 네이티브 공유 객체 내에 GNU 빌드 ID가 있어야 합니다. 각 바이너리에서 readelf -n을 실행하여 이 ID가 있는지 확인할 수 있습니다. 빌드 ID가 없는 경우 빌드 시스템의 플래그에 -Wl,--build-id를 추가하여 문제를 해결하세요.

3단계(선택사항): 라이브러리 모듈 및 외부 종속 항목 기호 업로드

기호 업로드 태스크에서는 CMake와 같은 표준 NDK 빌드 도구를 사용하여 앱 모듈의 Gradle 빌드의 일부로 네이티브 라이브러리를 빌드한다고 가정합니다. Gradle 내에서 맞춤설정된 NDK 빌드 프로세스를 사용하거나 네이티브 라이브러리가 라이브러리 Ehsms 기능 모듈에 빌드되었거나 타사에서 제공하는 경우 삭제되지 않은 라이브러리의 경로를 명시적으로 지정해야 할 수 있습니다. firebaseCrashlytics 확장 프로그램은 이를 수행하기 위한 unstrippedNativeLibsDir 속성을 제공합니다.

앱 수준 build.gradle 파일에 다음을 추가합니다.

// …
android {
    // ...
    buildTypes {
        release {
            firebaseCrashlytics {
                nativeSymbolUploadEnabled true
                unstrippedNativeLibsDir file("path/to/unstripped/dir")
            }
        }
    }
}

Crashlytics 플러그인은 지정된 디렉터리와 모든 하위 디렉터리에서 .so 확장자를 포함하는 네이티브 라이브러리를 검색합니다. 그러면 Crashlytics가 이러한 모든 라이브러리에서 디버깅 기호를 추출하여 Firebase 서버에 업로드합니다.

unstrippedNativeLibsDir 속성은 org.gradle.api.Project#files(Object...)에 허용되는 모든 인수(java.lang.String, java.io.File, org.gradle.api.file.FileCollection 포함)를 허용합니다. 목록이나 FileCollection 인스턴스를 제공하여 단일 빌드 버전에 여러 디렉터리를 지정할 수 있습니다.

4단계(선택사항): NDK 비정상 종료 보고서 맞춤설정

필요에 따라 C++ 코드에 crashlytics.h 헤더를 포함하여 로그, 커스텀 키, 사용자 ID와 같은 NDK 비정상 종료 보고서에 메타데이터를 추가할 수도 있습니다. crashlytics.hFirebase Android SDK GitHub 저장소에 헤더 전용 C++ 라이브러리로 제공됩니다. NDK C++ API 사용에 대한 안내는 헤더 파일의 설명을 참조하세요.

5단계(선택사항): 기호화를 위해 Breakpad 기호 파일 사용 설정

Crashlytics Gradle 플러그인은 다음 기능을 제공합니다.

  • 삭제되지 않은 네이티브 바이너리를 처리하여 기호 파일을 생성합니다.
  • 생성된 기호 파일을 나중에 네이티브 충돌을 기호화할 때 사용할 수 있도록 서버에 업로드합니다.

Crashlytics Gradle 플러그인은 다음과 같은 두 가지 유형의 기호 파일 형식을 지원합니다.
Crashlytics 기호 파일(cSYM)과 Breakpad 기호 파일

Breakpad에서 생성된 기호 파일에는 Crashlytics에서 생성한 기호 파일보다 많은 정보가 포함되어 있습니다. 여기에는 해제 프로세스에서 스택 프레임 계산을 돕는 데 사용하는 호출 프레임 정보(Call Frame Info)가 포함됩니다. CFI를 사용하면 특히 게임 및 미디어 앱과 같이 고도로 최적화된 애플리케이션의 고해상도 스택 트레이스가 생성됩니다.

Breakpad 기반 기호 파일 생성기를 다음 두 가지 방법 중 하나로 사용 설정할 수 있습니다.

  • 옵션 1: build.gradle 파일의 firebaseCrashlytics 확장 프로그램을 통해 사용 설정

    앱 수준 build.gradle 파일에 다음을 추가합니다.

    android {
      // ...
      buildTypes {
        // ...
        release {
          // ...
          firebaseCrashlytics {
            // existing; required for either symbol file generator
            nativeSymbolUploadEnabled true
            // Add this optional new block to specify breakpad() or csym()
            symbolGenerator {
               breakpad()
            }
          }
        }
      }
    }
    

    기본 Crashlytics 기호 파일 생성기로 다시 전환하려면 다음 중 하나를 수행하면 됩니다.

    • 플러그인은 기본적으로 Crashlytics 기호 파일 생성기를 사용하므로 symbolGenerator 블록을 완전히 생략합니다.

    • 블록을 유지하되 breakpad()csym()으로 변경합니다.

  • 옵션 2: Gradle 속성 파일의 속성 줄을 통해 사용 설정

    com.google.firebase.crashlytics.symbolGenerator 속성을 사용하여 사용할 기호 파일 생성기를 제어할 수 있습니다. 유효한 속성 값은 breakpad 또는 csym입니다. 지정하지 않으면 현재 기본값은 csym과 같지만 이후 버전에서 변경될 수 있습니다.

    Gradle 속성 파일을 수동으로 업데이트하거나 명령줄을 통해 파일을 업데이트할 수 있습니다. 예를 들어 Breakpad 기호 파일 생성기를 사용 설정하려면 다음 명령어와 같이 breakpad 값을 지정합니다.

    ./gradlew -Pcom.google.firebase.crashlytics.symbolGenerator=breakpad \
    app:assembleRelease app:uploadCrashlyticsSymbolFileRelease
    

6단계: 비정상 종료 보고서 확인

Crashlytics에서 앱을 빌드하고 기호를 업로드하고 네이티브 충돌을 강제 적용하여 NDK 비정상 종료를 제대로 보고하는지 확인합니다. 비정상 종료가 발생하면 Crashlytics에서 보고서를 보낼 수 있도록 앱을 다시 시작해야 합니다. 그러면 몇 분 내로 Firebase Console에 오류가 표시됩니다.

문제 해결

Firebase Console과 logcat에 서로 다른 스택 트레이스가 보이는 경우 문제 해결 가이드를 참조하세요.