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

3
我在Android Studio中有一个项目,其中包含使用JNI调用一些本地库的Android Java服务。
基本上,我编译了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.stackoverflowapp
        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

作为我的应用程序是安卓系统的一部分,因此进行了平台签名。
我使用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相关的stackoverflow文章。此外,我还使用"crashlytics、ndk和symbols"的任何组合进行了谷歌搜索。

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

  • Android Studio:3.5.1
  • Gradle:5.4.1
  • Gradle插件:3.5.2
  • Fabric Gradle插件:1.31.2

非常感谢。

3个回答

2
你可能想要考虑升级到新的(非 Fabric)Crashlytics SDK。它很可能是 fabric 的路线图替代品。

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

并且

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

尽管在撰写本文时它仍处于Beta版本,但我最近相当容易地转换到了它。 在此过程中,我还能够停止使用原生库(libCrashlytics)及其头文件。

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

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

请务必使用你在productFlavorsbuildTypes块中定义的风味和构建类型替换<Flavor><BuildType>

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

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>


感谢您的回复。我已经根据这两个URL升级了我的项目,但问题仍然存在。它正在上传崩溃日志,但是崩溃日志是空的,所有帧都丢失了。我不知道该怎么做才能获得适当的NDK崩溃日志...您能帮我吗?我是否忘记了任何步骤?尽管我正在上传符号,但似乎它们没有被正确上传... - Javier Rodriguez
我将更新我的答案,加入一些Gradle相关内容,以涵盖符号文件上传。 - ShellDude
看起来上传成功了: “Crashlytics 符号文件已成功上传;正在删除本地的 csym 文件:” 我需要以某种方式配置 Cmake 吗? - Javier Rodriguez
可能是我使用的编译器有问题吗?你用的是哪个编译器?gcc 还是 clang? - Javier Rodriguez
嗨!我想我找到了解决方案。在我的情况下,由于要求,我们的本地库需要打包在APK中,这意味着当APK被安装时,库将不会被提取。(在清单中添加android:extractNativeLibs="false")。如果我提取库,则本地崩溃将得到适当的报告。 - Javier Rodriguez
显示剩余3条评论

0
在我的情况下,将-Wl,--build-id添加到编译器标志中解决了这个问题。看起来Crashlytics无法将接收到的崩溃报告与上传的符号匹配。

最终,我刚刚与Firebase支持团队交谈,他们找到了问题并已经解决。问题与我的库安装位置有关,因为由于设计限制,我的库必须打包在apk中而不是安装在外部。 - Javier Rodriguez

0

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


1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接