1

I am trying to make use of the (experimental) native NDK support in Android Studio. I am new to working with Gradle. The project I am trying to build uses outside libraries which are to be compiled as static libraries when compiling the project and then be used within it. How can I do this?

To elaborate - There is C++ code in the default src/main/jni, it compiles properly and it can be seen properly in Android Studio under the jni folder. The project uses external C++ static libraries - some are compiled, some not. I need the project and the libraries to be built correctly and the code t obe visible where possible.

First of all, is there a way to be able to use Android.mk files? They are already available from a previous scheme to import the libraries but it seems that they are ignored now.

I've tried using srcDirs in android.source to add the libraries' paths and it works up to some point but strangely some of the paths are not found from the compiler and the compilation stops. Here's the code:

    android.sources {
        main {
            jni {
                source {
                    srcDirs += ["/../../../libPdf/"]

//                  aes library
                    srcDirs += ["/../../../libs/aes/include", "/../../../libs/aes"]

//                  jpeg library
                    srcDirs += ["/../../../libPdf/platform/Android", "/../../../libs/jpeg/jpeg-9"]
                }
            }
        }
    }

I've also tried adding the libraries as separate modules and then compiling each one of them in the project build.gradle (I saw this one in this sample: https://github.com/googlesamples/android-ndk/tree/master/hello-thirdparty) but I get this error even if I create a build.gradle file for the library:

Error:Configuration with name 'default' not found.

I don't know if I need an .iml file for the library, I don't have one and I don't know how to create one. I tried altering an existing one an putting it in the library but the same error occurred. Here is the code from the project's build.gradle:

apply plugin: 'com.android.model.library'
apply plugin: 'maven'

def jpeg_sdk_path = file(project(':jpeg').projectDir).absolutePath + "/jpeg-9"

model {

    android.buildTypes {
        release {
            consumerProguardFiles += file('proguard-project.txt')
        }
    }


    android.ndk {
        moduleName = "native"

        cppFlags += "-I${jpeg_sdk_path}".toString()
        ldLibs += ["jpeg"]

    }

    android {
        compileSdkVersion = 23
        buildToolsVersion = "21.1.2"

        defaultConfig.with {
            minSdkVersion.apiLevel = 14
            targetSdkVersion.apiLevel = 23
        }


        lintOptions.with {
            disable 'MissingTranslation'
        }

        //copy resources and stuff tasks

    }


}
dependencies {
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile files('libs/jsoup-1.7.3.jar')
    compile project(':jpeg')
}

And here is the settings.gradle:

include ':libPDF'
include ':PDFViewer'
include ':jpeg'
project(':jpeg').projectDir = new File(settingsDir, '/../../../libs/jpeg')

There are more libraries to be included but I am trying to import just one for now - jpeg, to see that it is working. I am trying to make local modules now and somehow connect them from gradle to the code which is elsewhere. I still get the same error - the build.gradle file does not seem to be found.

Any advice? Thanks in advance.

Edit: I managed to get the whole thing compiled but now I get linker errors. Here's the (shortened version of) build.gradle of the project:

apply plugin: 'com.android.model.library'
apply plugin: 'maven'

def jpeg_sdk_path = file(project(':jpeg').projectDir).absolutePath + "/../../../../../../../libs/jpeg/jpeg-9"
//other defs of paths

model {

android.buildTypes {
    release {
        minifyEnabled = false
        consumerProguardFiles += file('proguard-project.txt')
    }
    debug {
        minifyEnabled = false
        consumerProguardFiles += file('proguard-project.txt')
    }
}

android.sources {
    main {
        jni {
            source {
                srcDirs += ["src/main/jni/"]
                //lcms2
                srcDirs += [lcms2_out_path + "/src"]


                //freetype library
                include aes_path + "/aes_modes.c"
                include aes_path + "/aescrypt.c"
                include aes_path + "/aeskey.c"
                include aes_path + "/aestab.c"

 //                  jbig2 library
                srcDirs += [jbig2_path + "/src/jbig2", jbig2_path + "/include"]

//                  sfntly library
                include sfntly_path + "/sample/chromium/subsetter_impl.cc"
                //many other includes here

//                  jpeg library
                srcDirs += [ jpeg_main_path + "/../../../../../../../libPdf/platform/Android"]

                include jpeg_sdk_path + "/jaricom.c"
                include jpeg_sdk_path + "/jcapimin.c"
                //many other includes here

                //native libpdf library
                include libpdf_path+ "/PdfCatalog.cpp"
                //many other includes here

                //openssl library
                srcDirs += [openssl_path + "/lib/Android/armeabi-v7a/include"]
            }
        }

        jniLibs{
            source{
                srcDirs += ['/src/main/libs']
                srcDirs += [freetype_path + '/platform/Android/obj/local']
                srcDirs += [libpdf_path]
            }
        }

        resources.source.srcDirs += ['src/main/res']
    }


}

android.ndk {
    moduleName = "native"

    CFlags += "-I${openjpeg_path}/prebuilt/armeabi-v7a/include".toString() //figure out how to include for other flavors
    CFlags += "-I${jpeg_main_path}/../../../../../../../libPdf/platform/Android".toString()
    CFlags += "-I${jpeg_sdk_path}".toString()
    //other CFlags here
    CFlags += "-DSFNTLY_NO_EXCEPTION"
    CFlags += "-DU_STATIC_IMPLEMENTATION"
    cppFlags += CFlags

    abiFilters += "armeabi-v7a"
    ldFlags += "-L${freetype_src_path }/../platform/Android/obj/local/armeabi-v7a".toString()
    ldLibs += ["log", "android", "EGL", "GLESv1_CM", "ft2"]
    //other ldFlags and ldLibs - for the static .a libraries only
    stl = "gnustl_static"

}

compileOptions.with {
    sourceCompatibility=JavaVersion.VERSION_1_7
    targetCompatibility=JavaVersion.VERSION_1_7
}

android {
    compileSdkVersion = 23
    buildToolsVersion = "21.1.2"

    defaultConfig.with {
        minSdkVersion.apiLevel = 14
        targetSdkVersion.apiLevel = 23
    }

    lintOptions.with {
        disable 'MissingTranslation'
        abortOnError = false
    }

    //tasks for moving resources and stuff here
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.0.0'
compile files('libs/jsoup-1.7.3.jar')
compile project(':jpeg')
compile project(':freetype')
compile project(':lcms2')
compile project(':jbig2')
compile project(':aes')
compile project(':openjpeg')
compile project(':sfntly')
}

Now I get a lot of errors like that:

Error:(737, -1) Gradle: undefined reference to 'AndroidBitmap_getInfo'

I think I know why I get this - I should use something else instead of include to add individual files to the source set.

My question now is: How do I add individual files to a source set so they can be used by the compiler and later by the linker?

Nedko
  • 506
  • 5
  • 16
  • The issue is not clear. in which module do you have the error?Which is the configuration with the error? – Gabriele Mariotti Sep 12 '15 at 20:58
  • The module is 'jpeg' - it is empty, the only row of code is 'apply plugin: "java"'. I created a new native configuration and I am using it (just like in the official tutorial). Anyway, I got the compilation working. I have linker problems. I will update the question shortly. Thanks for trying to help! – Nedko Sep 16 '15 at 13:53
  • Documentation explicitly says that "pure native" modules are not supported *(yet?)* – Alex Cohn Sep 17 '15 at 08:56
  • for me, `include` statements inside `main.jni.sources` have no effect – Alex Cohn Sep 17 '15 at 12:47
  • I prefer to use the traditional **Android.mk** approach, today it is still much more flexible and supported. The trick is to disable the built-in gradle compile and link tasks, and add a manual `buildNative` task. – Alex Cohn Sep 17 '15 at 14:23
  • Actually, **Android.mk** was the previous approach which I am trying to migrate from because we want to debug both C++ and Java code from Android Studio. Do you know if `include` is the proper way to add a single file but it's just not supported (for now?) in `main.jni.sources`? I moved some files around and without using `include` the app compiled and executed. But now Android Studio won't recognize and connect the native declarations in Java with the C++ functions... So debugging works only for Java and I'm screwed again... – Nedko Sep 17 '15 at 18:31
  • Also, what does _pure native modules_ actually mean? My modules' gradle files are all empty with applied java plugin. I think all of this could be done without them but I wanted to move the declarations of native code source paths in each module once I had had success in debugging without the modules. – Nedko Sep 17 '15 at 18:38
  • *Pure native* is a module without Java sources, e.g. based on NativeActivity. Actually, there seem to still be problems with library modules that have native code (their AAR is not *exploded* as expected). Please check the hybrid solution I proposed for *[define LOCAL_SRC_FILES in ndk{} DSL](http://stackoverflow.com/questions/32636150/define-local-src-files-in-ndk-dsl/32640823#32640823)*. – Alex Cohn Oct 02 '15 at 18:39
  • add ldLibs.add("jnigraphics") it will solve your linker problem – Evgeni Roitburg Dec 20 '15 at 13:06
  • This is also answered here: http://stackoverflow.com/a/27737154/992509 – SJoshi Jan 06 '16 at 15:06

0 Answers0