Home » Android » android – I'm using SQLCIPHER to read or write database getting error

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

Posted by: admin June 15, 2020 Leave a comment

Questions:

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


    }
How to&Answers:

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

Answer:

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.

Answer:

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

Answer:

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

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