9

Hiee, i'm using sqlcipher to read the database but before reading the data it is giving the following error.Below is my logcat please have a look.

E/AndroidRuntime(21826): FATAL EXCEPTION: main
02-27 11:33:10.608: E/AndroidRuntime(21826): java.lang.UnsatisfiedLinkError: Native     method not found: net.sqlcipher.database.SQLiteDatabase.dbopen:(Ljava/lang/String;I)V
02-27 11:33:10.608: E/AndroidRuntime(21826): at net.sqlcipher.database.SQLiteDatabase.dbopen(Native Method)
02-27 11:33:10.608: E/AndroidRuntime(21826): at net.sqlcipher.database.SQLiteDatabase.    <init>(SQLiteDatabase.java:1942)
02-27 11:33:10.608: E/AndroidRuntime(21826): at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1920)
02-27 11:33:10.608: E/AndroidRuntime(21826): at example.SQLDemoActivity.onCreate(SQLDemoActivity.java:19)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.Activity.performCreate(Activity.java:5020)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.access$600(ActivityThread.java:149)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1300)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.os.Handler.dispatchMessage(Handler.java:99)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.os.Looper.loop(Looper.java:153)
02-27 11:33:10.608: E/AndroidRuntime(21826): at android.app.ActivityThread.main(ActivityThread.java:4987)
02-27 11:33:10.608: E/AndroidRuntime(21826): at java.lang.reflect.Method.invokeNative(Native Method)
02-27 11:33:10.608: E/AndroidRuntime(21826): at java.lang.reflect.Method.invoke(Method.java:511)
02-27 11:33:10.608: E/AndroidRuntime(21826): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
02-27 11:33:10.608: E/AndroidRuntime(21826): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
02-27 11:33:10.608: E/AndroidRuntime(21826): at dalvik.system.NativeStart.main(Native Method)

Below is the link from where i have got this sqlcipher class which i'm trying to run sqlcipher link

This is the class where i'm calling SQLiteDatabase.loadLibs(this), please have a look

 public class SQLDemoActivity extends Activity
      {
   EventDataSQLHelper eventsData;



   @Override
   public void onCreate(Bundle savedInstanceState)
   {
     super.onCreate(savedInstanceState);

//you must set Context on SQLiteDatabase first
SQLiteDatabase.loadLibs(this);

String password = "foo123";

eventsData = new EventDataSQLHelper(this);

//then you can open the database using a password
SQLiteDatabase db = eventsData.getWritableDatabase(password);

for (int i = 1; i < 100; i++)
    addEvent("Hello Android Event: " + i, db);

    db.close();

    db = eventsData.getReadableDatabase(password);

     Cursor cursor = getEvents(db);
     showEvents(cursor);

     db.close();

   }

   @Override
   public void onDestroy() {
     eventsData.close();
   }

   private void addEvent(String title, SQLiteDatabase db) {

     ContentValues values = new ContentValues();
     values.put(EventDataSQLHelper.TIME, System.currentTimeMillis());
          values.put(EventDataSQLHelper.TITLE, title);
     db.insert(EventDataSQLHelper.TABLE, null, values);
   }

   private Cursor getEvents(SQLiteDatabase db) {

     Cursor cursor = db.query(EventDataSQLHelper.TABLE, null, null, null, null,
    null, null);

     startManagingCursor(cursor);
     return cursor;
   }

   private void showEvents(Cursor cursor) {
StringBuilder ret = new StringBuilder("Saved Events:\n\n");
while (cursor.moveToNext()) {
  long id = cursor.getLong(0);
  long time = cursor.getLong(1);
  String title = cursor.getString(2);
  ret.append(id + ": " + time + ": " + title + "\n");
}

Log.i("sqldemo",ret.toString());
   }
 }

And below is the method body

public class SQLiteDatabase extends SQLiteClosable {
private static final String TAG = "Database";
private static final int EVENT_DB_OPERATION = 52000;
private static final int EVENT_DB_CORRUPT = 75004;

public int status(int operation, boolean reset){
    return native_status(operation, reset);
}

private static void loadICUData(Context context, File workingDir)
{

    try {
        File icuDir = new File(workingDir, "icu");
        if(!icuDir.exists()) icuDir.mkdirs();
        File icuDataFile = new File(icuDir, "icudt46l.dat");
        if(!icuDataFile.exists()) {
            ZipInputStream in = new ZipInputStream(context.getAssets().open("icudt46l.zip"));
            in.getNextEntry();
            OutputStream out =  new FileOutputStream(icuDataFile);
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) 
            {
                out.write(buf, 0, len);
            }
            in.close();
            out.flush();
            out.close();
        }
    }
    catch (Exception e)
    {
        Log.e(TAG, "Error copying icu data file", e);
    }
}

public static void loadLibs (Context context) 
{
    loadLibs(context, context.getFilesDir());
}





  public static void loadLibs (Context context, File workingDir)
{
    System.loadLibrary("stlport_shared");
    System.loadLibrary("sqlcipher_android");
    System.loadLibrary("database_sqlcipher");

    boolean systemICUFileExists = new File("/system/usr/icu/icudt46l.dat").exists();

    String icuRootPath = systemICUFileExists ? "/system/usr" : workingDir.getAbsolutePath();
    setICURoot(icuRootPath);
    if(!systemICUFileExists)
    {
        loadICUData(context, workingDir);
    }
}


    }

4 Answers 4

13

That error usually occurs if you have not called SQLiteDatabase.loadLibs() before attempting to use the database.

Sign up to request clarification or add additional context in comments.

5 Comments

pls have a look at my code, i have used a method named loadLibs()
i have done the same, have a look, i have put the code of the class where i have called loadLibs(). After all this i have got that exception
@Yushi: Your code and your stack trace do not match. Your stack trace shows that your onCreate() is calling the constructor for SQLiteDatabase.
@CommonsWare I am calling SQLiteDatabase.loadLibs(this) on Splash screen and my app is working fine. But getting same error(UnsatisfiedLinkError) very often not every time. Scnerio is :- 1. making a connection to DB. 2. Device in Ideal State. 3. Try to open database its tends to crash.
@HradeshKumar Have you found any solution?
3

The UnsatisfiedLinkError is due to the native libraries not being included with your application. For an example on integrating SQLCipher with an existing application, please review this tutorial. Alternatively, take a look at the SQLCipher for Android test suite.

1 Comment

Hello Sir, I am also getting the same issue , when i am going to update the exiting database with encrpted one. Yet now i am using the latest version, Could you please help me on it. Thanks
1

@CommonsWare is correct and you down-voted it.

When your app is being resumed from a long sleep, the libs have been cycled out and thus restoring state is crashing because libs are absent.

Put your SQLiteDatabase.loadLibs(this); ahead of super.onCreate(savedInstanceState)

@Override
public void onCreate(Bundle savedInstanceState) {

    //you must set Context on SQLiteDatabase first
    SQLiteDatabase.loadLibs(this);

    super.onCreate(savedInstanceState);

2 Comments

Are you saying it is not sufficient to do something like static boolean LIBS_LOADED = false; ... if (!LIBS_LOADED) { SQLiteDatabase.loadLibs(this); LIBS_LOADED = true; }. If I understand you correctly, LIBS_LOADED would remain true though the libs may have been recycled. Please can you point to some evidence to support this?
I may have misread the stack trace. My case was that super.onCreate(savedInstanceState); was recreating other fragments that referenced SQLCipher, which was definitely happening according to what I mentioned. In your case, it may have been simply not including the shared objects as Nick pointed out.
0

If SQLiteDatabase.loadLibs() is there, just make sure you add these lines to ProGuard file:

#Keep SQLCypher classes
-keep class net.sqlcipher.** { *; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.