Reputation: 23
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
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
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