1

I got a problem in initalizing Crashlytics for Android. The Java part works correctly but i cannot make NDK part to work because crashlytics_init() return a null value;

My project/build.gradle

buildscript {
    repositories {
        jcenter()
        google()
        maven {
            url 'https://maven.fabric.io/public'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
        classpath 'io.fabric.tools:gradle:1.24.4'
        classpath 'com.google.gms:google-services:3.1.0'
    }
}

allprojects {
    repositories {
        jcenter()
        google()

        maven {
            url 'https://maven.fabric.io/public'
        }

    }
}

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

app/build.gradle containing

compileSdkVersion 26

android {

    defaultConfig {
        ...
        minSdkVersion 19
        targetSdkVersion 22
        ...
    }

    ...
}

crashlytics {
    enableNdk true
    manifestPath 'C:\\full\\path\\to\\manifest\\AndroidManifest.xml'
}

dependencies {
    implementation 'com.google.firebase:firebase-crash:11.6.0'
    compile fileTree(include: ['*.jar'], dir: 'libs')

    compile('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') {
        transitive = true
    }
    compile('com.crashlytics.sdk.android:crashlytics-ndk:1.1.6@aar') {
        transitive = true;
    }

    compile 'com.google.firebase:firebase-core:11.6.0'

    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:26.1.0'
    compile 'com.android.support:support-v4:26.1.0'
    compile 'org.apache.commons:commons-compress:1.12'
    compile 'org.tukaani:xz:1.5'
}

main activity code

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    jniCrashlyticsInit();

    ...
}

and the native content of jniCrashlyticsInit()

void Java_com_my_app_MainActivity_jniCrashlyticsInit(JNIEnv *env,
                                                     jobject thiz)
{
    crashlytics = crashlytics_init();

    if (crashlytics == NULL)
        log("CRASHLYTICS NULL");
    else
        log("CRASHLYTICS NON NULL");
}

As you imagine, "CRASHLYTICS NULL" is logged and it cannot initialize all the stuff. I've put logs also inside crashlytics.h and it happens to fail on this line (returning a null value)

__crashlytics_unspecified_t* ctx = ((__crashlytics_initialize_t) sym_ini)();

Since i got no further infos, i really don't know how to proceed. Ideas?

Some info more: I use Android studio 3.0.0, and the NDK libraries are compiled manually with the following command

/cygdrive/c/Android/ndk-r15c/ndk-build.cmd NDK_DEBUG=0 APP_BUILD_SCRIPT=./Android.mk NDK_PROJECT_PATH=. APP_PLATFORM=android-19    

**** Update November 20th ****

As suggested by Todd Burner, I switched from "compile" to "implementation" on build.gradle from

compile('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') {
    transitive = true
}
compile('com.crashlytics.sdk.android:crashlytics-ndk:1.1.6@aar') {
    transitive = true;
}

to

implementation('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') {
    transitive = true
}
implementation('com.crashlytics.sdk.android:crashlytics-ndk:1.1.6@aar') {
    transitive = true;
}

then i ran

./gradlew assemble --refresh-dependencies

Unfortunally, crashlytics_init() still returns NULL

Davide Berra
  • 6,387
  • 2
  • 29
  • 50
  • Thanks for reaching out. We don't yet officially support AS 3 and that could explain this. Can you let me know if you have run into any issues with AS 2.x.x. Was this project migrated or was it setup as a new project in AS 3? Thanks! – Todd Burner Nov 15 '17 at 16:41
  • Thank you for reply! Project is 2 years old and I moved to AS 3 last week but i tried to use Crashlytics yesterday for the first time. Therefore i got no idea if it worked on AS 2. Sorry :( BTW, java crashes are perfectly detected and gathered. – Davide Berra Nov 15 '17 at 16:48
  • Can you try switching compile to implementation and running ./gradlew assemble --refresh-dependencies Thanks! – Todd Burner Nov 17 '17 at 18:43
  • Mr Burner, i did what you've suggested (pls check the updated question). No luck X( – Davide Berra Nov 20 '17 at 08:54
  • Maybe you forgot to initialize CrashlyticsNdk on Java side? See it here, it helped me: https://stackoverflow.com/questions/47211657/crashlytics-ndk-fails-to-load P.S. Crashlytics NDK documentation is bad: it lacks a lot of information and examples... – Anton Breusov Feb 27 '18 at 16:48

1 Answers1

0

I struggled days with this same issue. In my case I would blame partly the not-so-very-thorough documentation in the Fabric website and partly the lack of my reading comprehension.

I cannot be sure if you experience just the same thing, but my problem was that I tried to load Crashlytics NDK twice.

If you do the initialization from java like this:

Fabric.with(this, new Crashlytics(), new CrashlyticsNdk()); 

the native Crashlytics is automatically loaded and you don't need to initialize Crashlytics from C++. If you step into the decompiled Crashlytics .class files starting from CrashlyticsNdk.class you can see that JniNativeApi.class already calls System.loadLibrary("crashlytics").

In fact, if you still try to initialize Crashlytics from native side after that, the line

__crashlytics_unspecified_t* ctx = ((__crashlytics_initialize_t) sym_ini)();

will return NULL because the library has been already loaded.

What confused me is that the Official Fabric documentation doesn't say with bright red flashing letters that if you call new CrashlyticsNdk() from Java, you shouldn't try to load native Crashlytics from C++. To be fair, the documentation does say the following: In the process of initialization via Fabric.with(), the NDK Kit uses System.loadLibrary to load libcrashlytics. But it's a single line right before the Native API explanation starts and is easily overlooked.

Scam
  • 552
  • 5
  • 21
  • I tried this and sym_ini still returns NULL. The documentation says that when crashlytics_init is called, the library has already been loaded by new CrashlyticsNdk(). I think this is how it's supposed to work. – David Buck Mar 21 '18 at 22:04
  • If sym_ini returns NULL, then you didn't really try it, because my solution was not to call crashlytics_init() at all. Just load the library from java side with new CrashlyticsNdk() and do nothing in C++ side. Then cause a test crash in C++ side. At least in my project I can see the native crash dump in Fabric. – Scam Mar 22 '18 at 12:06
  • My objective was to be able to annotate additional information in the C crash reports. The documentation states that this is possible through the crashlytics_context_t::log method but you need a crashlytics context in order to call that. I can't get a crashlytics context unless I call crashlytics_init(). – David Buck Mar 23 '18 at 12:39