I m getting unsatisfied link error in native method
Logcat main exception
UnsatisfiedLinkError: Native method not found: rg.sqlite.database.sqlite.SQLiteConnection.nativeHasCodec:()Z
Complete Logcat
02-04 16:29:12.807: E/AndroidRuntime(5087): FATAL EXCEPTION: main
02-04 16:29:12.807: E/AndroidRuntime(5087): java.lang.UnsatisfiedLinkError: Native method not found: org.sqlite.database.sqlite.SQLiteConnection.nativeHasCodec:()Z
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteConnection.nativeHasCodec(Native Method)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteConnection.hasCodec(SQLiteConnection.java:160)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteDatabase.hasCodec(SQLiteDatabase.java:2195)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteConnectionPool.setMaxConnectionPoolSizeLocked(SQLiteConnectionPool.java:952)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteConnectionPool.<init>(SQLiteConnectionPool.java:153)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:179)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
02-04 16:29:12.807: E/AndroidRuntime(5087): at org.sqlite.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
02-04 16:29:12.807: E/AndroidRuntime(5087): at com.example.samplesqlitedb.SearchDataDB.getAutoSuggestion(SearchDataDB.java:33)
02-04 16:29:12.807: E/AndroidRuntime(5087): at com.example.samplesqlitedb.MainActivity$2.onClick(MainActivity.java:56)
02-04 16:29:12.807: E/AndroidRuntime(5087): at android.view.View.performClick(View.java:4084)
02-04 16:29:12.807: E/AndroidRuntime(5087): at android.view.View$PerformClick.run(View.java:16966)
02-04 16:29:12.807: E/AndroidRuntime(5087): at android.os.Handler.handleCallback(Handler.java:615)
02-04 16:29:12.807: E/AndroidRuntime(5087): at android.os.Handler.dispatchMessage(Handler.java:92)
02-04 16:29:12.807: E/AndroidRuntime(5087): at android.os.Looper.loop(Looper.java:137)
02-04 16:29:12.807: E/AndroidRuntime(5087): at android.app.ActivityThread.main(ActivityThread.java:4745)
02-04 16:29:12.807: E/AndroidRuntime(5087): at java.lang.reflect.Method.invokeNative(Native Method)
02-04 16:29:12.807: E/AndroidRuntime(5087): at java.lang.reflect.Method.invoke(Method.java:511)
02-04 16:29:12.807: E/AndroidRuntime(5087): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
02-04 16:29:12.807: E/AndroidRuntime(5087): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
02-04 16:29:12.807: E/AndroidRuntime(5087): at dalvik.system.NativeStart.main(Native Method)
Custom Java file SQLiteConnection https://www.dropbox.com/s/5ex6u9rzkwb7kqq/SQLiteConnection.java error on line no. 160
Here is the source cpp files from where i have compiled and created the binary "libsqliteX.so" file http://www.sqlite.org/android/tree?ci=trunk&re=jni|src/org/sqlite/data&expand
my .so file https://www.dropbox.com/s/d0u5pyhke54tcd6/libsqliteX.so
so i think i have to modify in the native method to resolve this problem
static jboolean nativeHasCodec(JNIEnv* env, jobject clazz){
#ifdef SQLITE_HAS_CODEC
return true;
#else
return false;
#endif
}
Here is CDT GLOBAL BUILD CONSOLE
**** Build of configuration Default for project CustomSqlite ****
D:\software\adt-bundle-windows-x86-20130522\adt-bundle-windows-x86-20130522\android-ndk-r9-windows-x86\android-ndk-r9\ndk-build.cmd all
"Compile++ thumb : sqliteX <= android_database_SQLiteCommon.cpp
"Compile++ thumb : sqliteX <= android_database_SQLiteConnection.cpp
"Compile++ thumb : sqliteX <= android_database_SQLiteGlobal.cpp
"Compile++ thumb : sqliteX <= android_database_SQLiteDebug.cpp
"Compile++ thumb : sqliteX <= JNIHelp.cpp
"Compile++ thumb : sqliteX <= JniConstants.cpp
"Compile thumb : sqliteX <= sqlite3.c
SharedLibrary : libsqliteX.so
Install : libsqliteX.so => libs/armeabi/libsqliteX.so
**** Build Finished ****
**** Build of configuration Default for project CustomSqlite ****
D:\software\adt-bundle-windows-x86-20130522\adt-bundle-windows-x86-20130522\android-ndk-r9-windows-x86\android-ndk-r9\ndk-build.cmd all
Install : libsqliteX.so => libs/armeabi/libsqliteX.so
**** Build Finished ****
so i think .so was generated properly
Here is my Customsqlite.java
it is having methods
package org.sqlite.app.customsqlite;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import org.sqlite.database.DatabaseErrorHandler;
import org.sqlite.database.sqlite.SQLiteDatabase;
import org.sqlite.database.sqlite.SQLiteOpenHelper;
import org.sqlite.database.sqlite.SQLiteStatement;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
class DoNotDeleteErrorHandler implements DatabaseErrorHandler {
private static final String TAG = "DoNotDeleteErrorHandler";
public void onCorruption(SQLiteDatabase dbObj) {
Log.e(TAG,"Corruption reported by sqlite on database: " + dbObj.getPath());
}
}
public class CustomSqlite extends Activity {
private TextView myTV;
EditText query;
File DB_PATH;
String searchedword;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myTV = (TextView) findViewById(R.id.tv_widget);
query = (EditText) findViewById(R.id.query);
}
public void report_version() {
SQLiteDatabase db = null;
SQLiteStatement st;
String res;
db = SQLiteDatabase.openOrCreateDatabase(":memory:", null);
st = db.compileStatement("SELECT sqlite_version()");
res = st.simpleQueryForString();
myTV.append("SQLite version " + res + "\n\n");
}
public void test_warning(String name, String warning) {
myTV.append("WARNING:" + name + ": " + warning + "\n");
}
public void test_result(String name, String res, String expected) {
myTV.append(name + "... ");
if (res.equals(expected)) {
myTV.append("ok\n");
} else {
myTV.append("FAILED\n");
myTV.append(" res= \"" + res + "\"\n");
myTV.append(" expected=\"" + expected + "\"\n");
}
}
/*
* * Test if the database at DB_PATH is encrypted or not. The db* is assumed
* to be encrypted if the first 6 bytes are anything* other than "SQLite".**
* If the test reveals that the db is encrypted, return the string*
* "encrypted". Otherwise, "unencrypted".
*/
public String db_is_encrypted() throws Exception {
FileInputStream in = new FileInputStream(DB_PATH);
byte[] buffer = new byte[6];
in.read(buffer, 0, 6);
String res = "encrypted";
if (Arrays.equals(buffer, (new String("SQLite")).getBytes())) {
res = "unencrypted";
}
in.close();
return res;
}
/*
* * Use a Cursor to loop through the results of a SELECT query.
*/
public void syno() throws Exception {
DB_PATH = new File("/storage/sdcard1/sk2.db");
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
Cursor c = db.rawQuery("SELECT synsetid, w2.lemma FROM sense LEFT JOIN word AS w2 ON w2.wordid=sense.wordid WHERE sense.synsetid IN (SELECT sense.synsetid FROM word AS w1 LEFT JOIN sense ON w1.wordid=sense.wordid WHERE w1.lemma='"+ searchedword+ "') AND w2.lemma<>'"+ searchedword + "'", null);
ArrayList<String> list1 = new ArrayList<String>();
if (c != null) {
if (c.getCount() > 0) {
c.moveToFirst();
do {
list1.add(c.getString(1));
} while (c.moveToNext());
}
myTV.append("\n\nSYNONYM " + list1.toString());
}
db.close();
}
/*
* * If this is a SEE build, check that encrypted databases work.
*/
public void anto() throws Exception {
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
Cursor c = db.rawQuery("SELECT DISTINCT(w2.lemma) as lemma from word w1 left join sense se1 on w1.wordid = se1.wordid left join synset sy1 on se1.synsetid = sy1.synsetid left join lexlinkref on sy1.synsetid = lexlinkref.synset1id and w1.wordid = lexlinkref.word1id left join word w2 on lexlinkref.word2id = w2.wordid where w1.lemma = '"+ searchedword + "' and lexlinkref.linkid=30",null);
ArrayList<String> list1 = new ArrayList<String>();
if (c.getCount() > 0) {
c.moveToFirst();
do {
list1.add(c.getString(0));
} while (c.moveToNext());
}
myTV.append("\n\nANTONYMS "+list1.toString());
db.close();
}
class MyHelper extends SQLiteOpenHelper {
public MyHelper(Context ctx) {
super(ctx, DB_PATH.getPath(), null, 1);
}
public void onConfigure(SQLiteDatabase db) {
db.execSQL("PRAGMA key = 'secret'");
}
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE t1(x)");
}
public void onUpgrade(SQLiteDatabase db, int iOld, int iNew) {
}
}
/*
* * If this is a SEE build, check that SQLiteOpenHelper still works.
*/
public void def() throws Exception {
DB_PATH = new File("/storage/sdcard1/sk2.db");
String DEFINITION = "select pos, definition, sample FROM word INNER JOIN sense ON word.wordid = sense.wordid INNER JOIN synset ON sense.synsetid = synset.synsetid LEFT JOIN sample ON sample.synsetid = synset.synsetid WHERE lemma ='"+ searchedword + "'";
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
ArrayList<String> list1 = new ArrayList<String>();
Cursor mcursor = db.rawQuery(DEFINITION, null);
mcursor.moveToFirst();
if (mcursor.getCount() > 0) {
do {
list1.add(mcursor.getString(1));
} while (mcursor.moveToNext());
}
myTV.append("\nDEFINATION " + list1.toString());
db.close();
}
public void run_the_tests(View view) {
System.loadLibrary("sqliteX");
myTV.setText("");
searchedword = query.getText().toString();
try {
report_version();
def();
syno();
anto();
} catch (Exception e) {
myTV.append("Exception: " + e.toString() + "\n");
myTV.append(android.util.Log.getStackTraceString(e) + "\n");
}
}
}
Thanks
UnsatisfiedLinkError runtime error. More specifically, this error is thrown whenever the JVM is unable to find an appropriate native-language definition of a method declared native , while attempting to resolve the native libraries at runtime [2].
Native Method Libraries are libraries that are written in other programming languages, such as C, C++, and assembly. These libraries can be loaded through JNI. So, the picture you posted is saying that JNI allows access to Native Method Libraries. Follow this answer to receive notifications.
library. path is a System property, which is used by Java programming language, mostly JVM, to search native libraries, required by a project. Similar to PATH and Classpath environment variable, java. library.
I have resolved this issue my self by adding
System.loadLibrary("sqliteX");
To each method where they are created
LIKE THIS:
public HashMap<String, ArrayList<String>> word_quiz(String qry) {
System.loadLibrary("sqliteX");
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH+ "/sk1.db", null);
Cursor mcursor = db.rawQuery(qry, null);
try {
mcursor.moveToFirst();
do {
list1.add(mcursor.getString(0));
list2.add(mcursor.getString(1));
} while (mcursor.moveToNext());
} catch (IndexOutOfBoundsException e) {
if (MainActivity.logcat_status) {
Log.e("Error", e + "");
}
}
mcursor.close();
mcursor = null;
HashMap<String, ArrayList<String>> final_list = new HashMap<String, ArrayList<String>>();
final_list.put("list1", list1);
final_list.put("list2", list2);
db.close();
return final_list;
}
Now its working fine
I think I can also use a constructor to load the library "sqliteX"
Thanks guys for considering my question :)
The exception originates from your code at com.example.samplesqlitedb.MainActivity$2.onClick()
at com/example/samplesqlitedb/MainActivity.java:56, but System.loadLibrary()
is called from org.sqlite.app.customsqlite.CustomSqlite.run_the_tests()
. There is no evidence that the org.sqlite.app.customsqlite.CustomSqlite
activity was even loaded into JVM when this happened.
I would suggest to load libsqliteX.so
from the static constructor of org.sqlite.database.sqlite.SQLiteConnection
class. Maybe you can find some better place - e.g. com.example.samplesqlitedb.SearchDataDB
class, or the class in your app that extends android.app.Application
(if you have such).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With