9

I am using the android gradle experimental plugin to build an app module with some native code. This native code uses a library with pre-built .so files, which I am bundling into a .aar file via an android library module. The .aar file builds fine, but how do I link the native code module in the app module to the pre-built .so files in the .aar module? The gradle experimental documentation doesn't mention this scenario.

Also, I'd like to package up include files in the .aar file if possible (although they shouldn't be packaged with the final application).

In /prebuiltlib:

build.gradle
-src/
--main/
---jniLibs/
----libfoo.so

Here are the gradle files:

/prebuiltlib/build.gradle

apply plugin: "com.android.model.library"
model {
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.3"

        defaultConfig {
            minSdkVersion.apiLevel = 21
            targetSdkVersion.apiLevel = 21
            versionCode 1
            versionName "1.0"

        }

        buildTypes {
            release {
                minifyEnabled false
                proguardFiles.add(file("proguard-rules.pro"))
            }
        }
    }
}

dependencies {
    compile fileTree(dir: "libs", include: ["*.jar"])
    compile "com.android.support:appcompat-v7:25.3.1"
}

Here is /app/build.gradle, note the ??? where I'm not sure what to put:

import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.model.application'

model {
    repositories {
        libs(PrebuiltLibraries) {
            // ??? is this right, and does this go into app/build.gradle or mylib/build.gradle?
            foo {
                binaries.withType(SharedLibraryBinary) {
                    sharedLibraryFile = file('???/libfoo.so')
                }
            }
        }
    }
    android {
        compileSdkVersion = 25
        buildToolsVersion = '25.0.3'

        defaultConfig {
            applicationId = 'com.jeremy.stackoverflow.sample'
            minSdkVersion.apiLevel = 21
            targetSdkVersion.apiLevel = 21
            versionCode = 1
            versionName = '1.0'
        }

        ndk {
            platformVersion = 21
            moduleName = 'native-activity'
            toolchain = 'gcc'
            toolchainVersion = '4.9'
            stl = 'gnustl_shared'
            abiFilters.add('armeabi-v7a')
            ldLibs.addAll(['log',
                           'android',
                           'EGL',
                           'GLESv2'
            ])
            // ??? How do I add include paths from the .aar module?
            cppFlags.add('-I' + file('???/include'))
            cppFlags.addAll(['-std=c++11', '-fexceptions'])
        }

        sources {
            main {
                jni {
                    dependencies {
                        // ??? Is this right?
                        library 'foo' linkage 'shared'
                    }
                }
                jniLibs {
                    source {
                        // ??? Do I need one of these for the libs in the .aar?
                        srcDir file('???/jniLibs')
                    }
                    dependencies {
                        // ??? Is this right?
                        library 'foo'
                    }
                }
            }
        }
        buildTypes {
            release {
                minifyEnabled = false
                proguardFiles.add(file('proguard-rules.pro'))
            }
        }
    }
}

dependencies {
    println rootProject.getName()
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile project(':prebuiltlib')
}
Jeremy Bell
  • 5,253
  • 5
  • 41
  • 63
  • 2
    I know google did this in their "ArCore C Sdk", but I couldn't implement it in my project. Did you manage to solve this? – Oren Bengigi Jun 04 '18 at 09:37

1 Answers1

0

Starting with Android Gradle Plugin 4.0, C/C++ dependencies can be imported from AARs linked in your build.gradle file. Gradle will automatically make these available to the native build system, but your build system must be configured to make use of the imported libraries and headers.

In gradle 4.0: add the following to your project's gradle.properties file:

android.enablePrefab=true

In gradle 4.1: add the following to the android block of your module's build.gradle file:

buildFeatures {
  prefab true
}

, if your application defines libapp.so and it uses cURL, your CMakeLists.txt should include the following:

add_library(app SHARED app.cpp)

# Add these two lines.
find_package(curl REQUIRED CONFIG)
target_link_libraries(app curl::curl)

app.cpp is now able to #include "curl/curl.h", libapp.so will be automatically linked against libcurl.so when building, and libcurl.so will be included in the APK.

Source: https://developer.android.com/studio/build/native-dependencies

AndrewBloom
  • 2,171
  • 20
  • 30
  • can you explain a bit more on this? It's not clear yet on which directory goes what. – eri0o Jan 22 '21 at 15:00
  • 1
    this is to use .so libraries inside an aar file. The aar file can come from a repository or be local (usually then copied on a libs folder). To import the aar file check this docs https://developer.android.com/studio/build/dependencies – AndrewBloom Jan 23 '21 at 23:11