I am trying my hands on developing a simple android application in which I am trying to use sqlcipher, which uses .so libraries internally. I have read the documentation on how to use sqlcipher with android app. I have followed the steps and it compiles without any error. But, at runtime it throws UnsatisfiedLinkError.

Googling around for it, I found that, gradle doesn't support .so libraries yet, but I found a hack here which I am trying to use. But it throws compile time error at line #40 on the gist which is,

tasks.withType(com.android.build.gradle.PackageApplicationTask) { pkgTask ->
    pkgTask.jniDir new File(buildDir, 'native-libs')


Could not find property 'com' on Project 'MyProject'

Here I am posting code from my build.gradle file.

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
apply plugin: 'android'

dependencies {
    compile files('libs/android-support-v4.jar')
    compile files('libs/commons-codec.jar')
    compile files('libs/guava-r09.jar')
    compile files('libs/sqlcipher.jar')

targetCompatibility = 1.6
sourceCompatibility = 1.6

android {
    target = 'android-14'

    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 16


task copyNativeLibs(type: Copy) {
    from(new File(project(':MyProject').buildDir, 'native-libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

tasks.withType(com.android.build.gradle.PackageApplicationTask) { pkgTask ->
    pkgTask.jniDir new File(buildDir, 'native-libs')

Can, anybody please help me on what I have done wrong or what should I do to include those .so libraries in my apk?

As I am new to android development and gradle, please apologize me if I have misunderstood something.

Solution 1

I've tried the solution presented in the accepted answer and it did not work for me. I wanted to share what DID work for me as it might help someone else. I've found this solution here.

Basically what you need to do is put your .so files inside a a folder named lib (Note: it is not libs and this is not a mistake). It should be in the same structure it should be in the APK file.

In my case it was:
|--|--|--.so files.

So I've made a lib folder and inside it an armeabi folder where I've inserted all the needed .so files. I then zipped the folder into a .zip (the structure inside the zip file is now lib/armeabi/*.so) I renamed the .zip file into armeabi.jar and added the line compile fileTree(dir: 'libs', include: '*.jar') into dependencies {} in the gradle's build file.

This solved my problem in a rather clean way.

Solution 2

To include native libraries you need:

  1. create "jar" file with special structure containing ".so" files;
  2. include that file in dependencies list.

To create jar file, use the following snippet:

task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/'

tasks.withType(Compile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)

To include resulting file, paste the following line into "dependencies" section in "build.gradle" file:

compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')

Solution 3

I had the same problem. Check out the comment in https://gist.github.com/khernyo/4226923#comment-812526

It says:

for gradle android plugin v0.3 use "com.android.build.gradle.tasks.PackageApplication"

That should fix your problem.