Yushi
Yushi

Reputation: 416

I'm using SQLCIPHER to read or write database getting error

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);
    }
}


    }

Upvotes: 9

Views: 7203

Answers (4)

lomza
lomza

Reputation: 9716

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

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

Upvotes: 0

Dan Davis
Dan Davis

Reputation: 579

@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);

Upvotes: 1

Nick Parker
Nick Parker

Reputation: 1388

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.

Upvotes: 3

CommonsWare
CommonsWare

Reputation: 1006674

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

Upvotes: 13

Related Questions