Arturo Ribes
Arturo Ribes

Reputation: 365

NDK messes with external dependency in Android Studio

I have been working on an app which uses an external library packaged in a .aar file. In the gradle file I only had to add

compile project(':empalink-2.0')

And it worked ok so far. Now I wanted to add a port of the libSVM library, which makes me to copy the jni directory into my app/src/main and then add some code from their gradle file, which ends up like this:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "23.0.0"

    defaultConfig {
        applicationId "com.csic.iiia.ActivityRecognition"
        minSdkVersion 19
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        ndk {
            moduleName "jnilibsvm" // <-- This is the name of my C++ module!
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets.main {
        jniLibs.srcDir 'src\\main\\libs'
        jni.srcDirs = []
    }

    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        def ndkDir = android.ndkDirectory
        commandLine "$ndkDir\\ndk-build.cmd",
                '-C', file('src\\main\\jni').absolutePath, // Change src/main/jni the relative path to your jni source
                '-j', Runtime.runtime.availableProcessors(),
                'all',
                'NDK_DEBUG=1'
    }

    task cleanNative(type: Exec, description: 'Clean JNI object files') {
        def ndkDir = android.ndkDirectory
        commandLine "$ndkDir\\ndk-build.cmd",
                '-C', file('src\\main\\jni').absolutePath, // Change src/main/jni the relative path to your jni source
                'clean'
    }

    clean.dependsOn 'cleanNative'

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn buildNative
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.loopj.android:android-async-http:1.4.6'
    compile project(':empalink-2.0')
    compile 'com.google.android.gms:play-services-appindexing:8.1.0'
    compile 'org.apache.commons:commons-math3:3.6.1'
}

The added parts are the defaultConfig.ndk and the build/cleanNative stuff.

Now when trying to execute the application, I receive the following error:

java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.csic.iiia.ActivityRecognition-1/base.apk"],nativeLibraryDirectories=[/data/app/com.csic.iiia.ActivityRecognition-1/lib/arm64, /data/app/com.csic.iiia.ActivityRecognition-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libempac.so"

That lilbempac.so is the .so file that comes in the .aar file that was working ok until I added the libSVM to the project. I guess that enabling NDK compilation somehow affected the linkage with the external dependency :empalink-2.0.

Upvotes: 0

Views: 396

Answers (1)

AudVid
AudVid

Reputation: 44

This is maybe a late answer but ... Empatica only provides the armeabi version of libempac.so. But if you add other native libraries, gradle will compute other architectures like armeabi-v7a, mips, mips64, etc. And so the libempac will be available only for one this architectures. So you need to disable compilation for other architecture than armeabi. You can do this by adding this in app build.gradle file :

android {
      [...]
    splits {
        abi {
            enable true
            reset()
            include  'armeabi'
            universalApk false
        }
    }

}

Upvotes: 2

Related Questions