Firebase Crashlytics Android NDK:崩溃报告上的空符号

Firebase Crashlytics Android NDK: empty symbols on crash reports

我在 Android Studio 中有一个项目包含 Android Java 通过 JNI 调用使用一些本机库的服务。

基本上,我有 2 个我编译的库和另一个预编译的库,所以我无法访问源代码。由于预编译库仅针对 armeabi-v7a 构建,因此我有一个 abiFilter。

在这里,我的/build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()

        maven { url 'https://maven.fabric.io/public' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        classpath 'io.fabric.tools:gradle:1.31.2'
        classpath 'com.google.gms:google-services:4.3.3'  // Google Services plugin

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()

    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

和我的/app/build.gradle(省略了合理的代码)

apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

def enableCrashlyticsNdk = true

repositories {
    jcenter()
    maven { url 'https://maven.fabric.io/public' }
}

android {
    signingConfigs {
        platformSignature {
            keyAlias "${platform_keystore_alias}"
            keyPassword "${platform_keystore_password}"
            storeFile file("${platform_keystore_path}")
            storePassword "${platform_keystore_password}"
        }
    }

    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    lintOptions {
        abortOnError false
    }

    defaultConfig {
        applicationId com.example.Whosebugapp
        minSdkVersion 26
        targetSdkVersion 28
        versionCode 1
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -Werror"
            }
        }
        ndk {
            // Specifies the ABI configurations of your native
            // libraries Gradle should build and package with your APK.
            abiFilters 'armeabi-v7a'
        }
    }

    buildTypes {
        release {
            minifyEnabled true
            jniDebuggable false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.platformSignature
        }
        debug {
            debuggable true
            jniDebuggable true
            versionNameSuffix = " (debug)"
            signingConfig signingConfigs.platformSignature
        }
    }

    android.applicationVariants.all { variant ->
        variant.outputs.all {
            outputFileName = buildOutputName(variant)
        }
    }

    packagingOptions {
        exclude 'jsr305_annotations/Jsr305_annotations.gwt.xml'
        exclude 'error_prone/Annotations.gwt.xml'
        exclude 'third_party/java_src/error_prone/project/annotations/Annotations.gwt.xml'
        exclude 'third_party/java_src/error_prone/project/annotations/Google_internal.gwt.xml'
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

ext {
    appCompatVersion = '28.0.0'
}

crashlytics {
    enableNdk enableCrashlyticsNdk
}

tasks.whenTaskAdded { task ->
    if (enableCrashlyticsNdk && task.name.startsWith('assemble')) {
        task.finalizedBy "crashlyticsUploadSymbols" + task.name.substring('assemble'.length())
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.leanback:leanback:1.0.0'
    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'com.google.android.exoplayer:exoplayer:r1.5.14'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
    implementation 'com.google.code.gson:gson:2.8.5'

    implementation 'com.google.firebase:firebase-analytics:17.2.1'
    implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
    implementation 'com.crashlytics.sdk.android:crashlytics-ndk:2.1.1'
}

apply plugin: 'com.google.gms.google-services'  // Google Play services Gradle plugin

由于我的应用程序是 Android 系统的一部分,因此使用平台签名进行签名。

我用 CMake 编译我的 2 个库。

我已按照 firebase 网站上的所有步骤进行操作:

  1. https://firebase.google.com/docs/android/setup
  2. https://firebase.google.com/docs/crashlytics/get-started?platform=android
  3. https://firebase.google.com/docs/crashlytics/ndk-reports

我在我的一个库中故意添加了一个崩溃,当应用程序崩溃时,Crashlytics 收集了崩溃并成功上传了崩溃报告。

CrashlyticsCore: Crashlytics report upload complete: 5DE66A450116-0001-1A8B-A3EE77BA9366

然后,当我转到 firebase 控制台时,我看到所有堆栈帧都(丢失)

Crashed: Thread #1
SIGSEGV 0x0000000000000028
-------------------------------------------
0 MyApp.apk (Missing)
1 libart.so (Missing)
2 (Missing)
3 (Missing)
4 (Missing)
5 (Missing)
6 (Missing)
7 libart.so (Missing)
8 libart.so (Missing)
9 libart.so (Missing)
10 (Missing)
11 libart.so (Missing)
12 (Missing)

查看 Crashlytics 构建日志,cSym 文件似乎已正确上传。

[DEBUG] (Execution worker for ':' Thread 6) com.crashlytics  - cSYM file(s) uploaded.

我不太确定这些符号是否已正确创建和上传,或者设备创建的崩溃报告是否存在问题。我担心这个问题与 android 权限有关,因为我的应用程序是系统应用程序。

我想我已经阅读了所有与 Crashlytics 和 NDK 相关的 Whosebug 帖子。此外,我还用谷歌搜索了与 "crashlytics, ndk and symbols".

相关的任何一种组合

最后,我使用的工具版本:

非常感谢。

您可能需要考虑升级到新的(非结构)Crashlytics SDK。据推测,它是 fabric 的路线图替代品。

https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android

https://firebase.google.com/docs/crashlytics/ndk-reports-new-sdk

虽然在撰写本文时它还处于 Beta 阶段,但我最近很容易转换到它。在此过程中,我还能够停止在我的本机代码中使用 fabric 本机库 (libCrashlytics) 及其 header。

此外,确保在构建过程中将符号正确上传到 Firebase/Fabric。您可能需要像这样作为 afterEvaluate 块的一部分明确地执行此操作:

afterEvaluate {
    if (gradle.startParameter.taskNames.contains(":app:assemble<Flavor><BuildType>")) {
        assemble<Flavor><BuildType>.finalizedBy(uploadCrashlyticsSymbolFile<Flavor><BuildType>)
    }
}

请务必将 <Flavor><BuildType> 替换为您在 productFlavorsbuildTypes 块中定义的风格和构建类型。

例如,以下风味/构建类型:

buildTypes {
    release {
        signingConfig signingConfigs.release
        buildConfigField "boolean", "RELEASE", "true"
        shrinkResources true
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    debug {
        buildConfigField "boolean", "RELEASE", "false"
        applicationIdSuffix '.debug'
        versionNameSuffix '-DEBUG'
        ext.alwaysUpdateBuildId = false
        crunchPngs false
    }
}

flavorDimensions "all"

productFlavors {
    fat {
        ndk {
            abiFilters "x86_64", "x86", "arm64-v8a", "armeabi-v7a"
        }
        dimension "all"
    }
}

会导致 assembleFatDebug 和 assembleFatRelease 任务,您需要相应地使用 uploadCrashlyticsSymbolFileFatDebug 和 uploadCrashlyticsSymbolFileFatRelease 任务来完成这些任务。

注意: 如果您仍在使用 Fabric,您想要完成 assemble* 任务的任务是 crashlyticsUploadSymbols<Flavor><BuildType>

在我的例子中,将 -Wl,--build-id 添加到编译器标志解决了这个问题。 Crashlytics 似乎无法将收到的崩溃报告与上传的符号相匹配。

我通过将 NDK 版本从 10d 替换为 13d 解决了这个问题。