Seppl linowitsch
Seppl linowitsch

Reputation: 23

can't include shared library in android studio

I'm having a hard time with including my own sqlite library (libsqliteX.so) in android studio:

I followed this guide and loaded this and compiled it with latest android NDK (r10e) (i just added "APP_ABI := xxx" to the Application.mk to build also x86 and armeabi-v7a versions of it) and got this: console output: s3.postimg.org/v83e8bwsz/ndk_build.jpg (cant post more than 2 links :D).

After that I have created a new app in android studio (v1.2.1.1) and create a new jnilibs-folder where I copied my .so files: s17.postimg.org/7vvvsao67/jni_Libs.jpg

I didn't change the build.gradle (gradle version 1.2.3) or anything, just compiled my app and the libraries are included in the apk (opened the .../app/build/outputs/apk/apk-debug.apk with winzip and there is a lib-folder with the libsqliteX.so files).

But now I don't know how to use that library in my project. I'm not able to add the line import org.sqlite.database...; (cant resolve symbol 'sqlite'), I'm not able to add that libraries in Project Structure -> Dependencies (only the default depencies that are also in the build.gradle are there:

compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.android.support:support-v4:22.1.1'

and if I just load the library with System.loadLibrary("sqliteX"); I got this error at runtime:

05-29 03:21:54.248    3450-3450/com.example.thele.geostuff D/dalvikvm﹕ Added shared lib /data/app-lib/com.example.thele.geostuff-1/libsqliteX.so 0x416f6428
05-29 03:21:54.288    3450-3450/com.example.thele.geostuff E/SQLiteConnection﹕ Unable to find class org/sqlite/database/sqlite/SQLiteCustomFunction
05-29 03:21:54.288    3450-3450/com.example.thele.geostuff W/dalvikvm﹕ JNI WARNING: JNI method called with exception pending
05-29 03:21:54.288    3450-3450/com.example.thele.geostuff W/dalvikvm﹕ in Ljava/lang/Runtime;.nativeLoad:(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String; (GetFieldID)
05-29 03:21:54.288    3450-3450/com.example.thele.geostuff W/dalvikvm﹕ Pending exception is:
05-29 03:21:54.297    3450-3450/com.example.thele.geostuff I/dalvikvm﹕ java.lang.NoClassDefFoundError: org/sqlite/database/sqlite/SQLiteCustomFunction

(changing dalvik to art throws a similar error (cant find the class))

I applied different methods to make it work (invalidate caches/restart, created a .jar file out of the .so file) but it didn't help. What I'm doing wrong?


Edit:

The complete build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.example.thele.geostuff"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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

Upvotes: 2

Views: 1334

Answers (2)

JulianHarty
JulianHarty

Reputation: 3286

I'd like to confirm and expand on Qylin's answer https://github.com/android/nowinandroid.git and the comment from Seppl (who wrote the question) as I followed their guidance to get SQLite working for native code where one of the C++ libraries required sqllite3.

The source code https://sqlite.org/android/doc/tip/sqlite3/src/main/jni/sqlite/android_database_SQLiteConnection.cpp which looks like it might be the reason the Java classes are required (in lines 890 to 909) reproduced below for ease of reference:

int register_android_database_SQLiteConnection(JNIEnv *env)
{
    jclass clazz;
    FIND_CLASS(clazz, "org/sqlite/database/sqlite/SQLiteCustomFunction");

    GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.name, clazz,
            "name", "Ljava/lang/String;");
    GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.numArgs, clazz,
            "numArgs", "I");
    GET_METHOD_ID(gSQLiteCustomFunctionClassInfo.dispatchCallback,
            clazz, "dispatchCallback", "([Ljava/lang/String;)V");

    FIND_CLASS(clazz, "java/lang/String");
    gStringClassInfo.clazz = jclass(env->NewGlobalRef(clazz));

    return jniRegisterNativeMethods(env, 
        "org/sqlite/database/sqlite/SQLiteConnection",
        sMethods, NELEM(sMethods)
    );
}

BTW: Android source has similar code: https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/jni/android_database_SQLiteConnection.cpp (This is an old version of Android, presumably newer releases have similar code.)

To add the Java files, I followed step 3 of the third option in the instructions of how to add the java bindings to an Android app (from https://sqlite.org/android/doc/trunk/www/install.wiki)

I downloaded the pre-compiled libraries for Android and the SQLite Android bindings from https://sqlite.org/download.html I've reproduced extracts here:

"3. Adding Source Code Directly to the Application To copy the SQLite Android bindings code into an application:

.. cut .. "

FYI: we used the pre-compiled libraries for Android rather than building them from source (which step 2 describes) as that fitted better in the codebase we were building where we build using cmake, meson, ninja, etc and didn't want to add ndk-build to the mix.

"3.3 Recursively copy the contents of the sqlite3/main/src/java/ directory to whereever the application java code is."

The necessary files were/are available in: https://sqlite.org/2024/sqlite-android-3460000.aar (from https://sqlite.org/download.html ) Precompiled Binaries for Android sqlite-android-3460000.aar (3.44 MiB) A precompiled Android library containing the core SQLite together with appropriate Java bindings, ready to drop into any Android Studio project.

A more rhetorical question is why the java classes and functions are used by the C++ code when SQLite is built for Android rather than a pure C/C++ implementation. However, it is what it is, and at least there's a way to get SQLlite working for native code on Android once the Java classes are compiled into the Android application.

Upvotes: 0

Qylin
Qylin

Reputation: 1601

To me the error

java.lang.NoClassDefFoundError: org/sqlite/database/sqlite/SQLiteCustomFunction

Seems to be a Java layer error, not a C level error. Because the *.c files doesn't have package/folder structure (like "org/sqlite/database...").

So my best guess is, some .class file are not in your apk. If I were you I'd use 7zip/winrar to unzip the apk and check if the org.sqlite.database.sqlite.SQLiteCustomFunction is there.

Actually, I believe the .so is successfully loaded.

Added shared lib /data/app-lib/com.example.thele.geostuff-1/libsqliteX.so 0x416f6428

Upvotes: 2

Related Questions