Issue
I have a project in Android Studio that consist on Android Java Services that uses some native libraries through JNI calls.
Basically, I have 2 libraries I compile and another library that is precompiled, so I don't have access to the source code. As the precompiled library is only built for armeabi-v7a, I have an abiFilter.
Here, my /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
}
and my /app/build.gradle (omitted the sensible code)
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
As my app is part of the Android system, it is signed with a platform signature.
I compile my 2 libraries with CMake.
I have followed all steps from the firebase web:
- https://firebase.google.com/docs/android/setup
- https://firebase.google.com/docs/crashlytics/get-started?platform=android
- https://firebase.google.com/docs/crashlytics/ndk-reports
I've added a crash intentionally within one of my libraries and when the app reaches crash, The Crashlytics gathered the crash and upload the crash report successfully.
CrashlyticsCore: Crashlytics report upload complete: 5DE66A450116-0001-1A8B-A3EE77BA9366
Then, when I go to the firebase console, I see that all stack frames are (missing)
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)
Reviewing the Crashlytics build logs, it seems like the cSym files are uploaded properly.
[DEBUG] (Execution worker for ':' Thread 6) com.crashlytics - cSYM file(s) uploaded.
I'm not really sure if the symbols are properly created and uploaded or if there is an issue with the crash reports created by the device. I'm afraid of the problem would be related with android permissions as my app is a system app.
I guess I've read all the stackoverflow posts related with Crashlytics and NDK. Also, I've also googled any kind of combination related with "crashlytics, ndk and symbols".
Finally, the tool versions I'm using:
- Android Studio: 3.5.1
- Gradle: 5.4.1
- Gradle plugin: 3.5.2
- Fabric gradle plugin: 1.31.2
Thank you so much.
Solution
You may want to consider upgrading to the new (non fabric) Crashlytics SDK. It is, assumedly, the roadmap replacement for fabric.
https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android
and
https://firebase.google.com/docs/crashlytics/ndk-reports-new-sdk
While it is in Beta as of this writing, I recently converted to it fairly easily. In the process I was also able to stop using the fabric native library (libCrashlytics) and its header in my native code.
Additionally, ensure you are properly uploading the symbols to Firebase / Fabric as part of your build process. You may need to do this explicitly as part of an afterEvaluate
block like so:
afterEvaluate {
if (gradle.startParameter.taskNames.contains(":app:assemble<Flavor><BuildType>")) {
assemble<Flavor><BuildType>.finalizedBy(uploadCrashlyticsSymbolFile<Flavor><BuildType>)
}
}
Be sure to replace <Flavor>
and <BuildType>
with the flavor and build type(s) you defined in your productFlavors
and buildTypes
blocks.
For example, the below flavor / build types:
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"
}
}
would result in assembleFatDebug and assembleFatRelease tasks that you'd need to finalize with uploadCrashlyticsSymbolFileFatDebug and uploadCrashlyticsSymbolFileFatRelease tasks accordingly.
NOTE:
If you are still using Fabric, the task you want to finalize your assemble*
task with is crashlyticsUploadSymbols<Flavor><BuildType>
.
Answered By - ShellDude
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.