How can I use ORMLite with SQLCipher together in Android?
Asked Answered
C

5

16

I would like to use OrmLite with SQLCipher in my Android project, but both libraries have their own abstract SQLiteOpenHelper class to implement. Java don't allow a class to extend two classes and if I implement separately, they will not communicate with each other.

How can I work with both together? How do I resolve the SQLiteOpenHelper implementation problem?

Cattycornered answered 7/2, 2012 at 13:5 Comment(2)
SQLCiphers version is a re-factored version of the SQLiteOpenHelper - i.e. it's not the same class - to get these two to work nicely together you're going to have to re-work the entire OrmLite library to use the SQLCipher-packages instead.Licentious
It sure would be awesome if OrmLite did this out-of-the-box. Also would be nice if SqlCipher came in a Maven artifact. They seem like two libraries that obviously need to work with each other (better).Bonaire
M
4

How can I use ORMLite with SQLCipher together in Android?

It should be possible @Bruno.

One way that should work is to just copy ORMLite's OrmLiteSqliteOpenHelper class into your project, rename it to LocalOrmLiteSqliteOpenHelper or something, and change the base class to be the SQLCipher helper class. I can't believe they didn't rename the class to be SQLCipherSQLiteOpenHelper. (grumble)

public abstract class LocalOrmLiteSqliteOpenHelper
    extends info.guardianproject.database.sqlcipher.SQLiteOpenHelper {

Another way would be to have your helper extend SQLCipher's SQLiteOpenHelper and then implement the various things you need from OrmLiteSqliteOpenHelper yourself. That would take a bit more work however. ORMLite has to do a little dance with database connections while the database is being created otherwise it goes recursive.

Let me know if either of these work.

Mastectomy answered 7/2, 2012 at 17:30 Comment(3)
I tried it but I am getting compile time errors EX:" new AndroidConnectionSource(this);"Relic
Same error. The constructor AndroidConnectionSource(OrmLiteSqliteOpenHelper) is undefined. Why is this answer accepted?Bebebebeerine
The answer is outdated. It was valid for older versions of ORMLite. So, guys, who are complaining, please hold on while someone will update the answerRue
I
6

I have distilled the answer by Rejinderi into a patch for ORMLite 4.43 and compiled it into a JAR file. To integrate it in your Android project, do the following:

  1. Follow the SQLCipher for Android HOWTO to get SQLCipher into your project
  2. Add ORMLite to your project (see What is a good tutorial for using ORMLite with SQLite and Android)
  3. Replace libs/ormlite-android.jar with ormlite-android-sqlcipher.jar
  4. Add your secret database password to the appropriate DB opening methods

However, you should not trust me to provide an unmanipulated JAR file and follow the build instructions in the patch instead.

EDIT: With the patched library, the calls to getReadableDatabase(), getWritableDatabase() and the OrmLiteSqliteOpenHelper constructor need to be passed the password as additional parameter. If you are using a DB helper, extend it appropriately to pass the password to OrmLiteSqliteOpenHelper.

Innards answered 8/2, 2013 at 14:30 Comment(7)
yeah? What's your db password? :)Erewhile
Mine is "password"; but what I was talking about is that the JAR file I provided might as well contain a sendCovertMessageTo("ge0rg", your_db_password) line...Innards
I didn't expect you too answer that. I guess that goes to prove your point. If it's about the same size as the original, where would you find the resources/means to send info somewhere? I'm genuinely curious. I have an interest and little understanding of security on the dalvik.Erewhile
I guess you could assume app permissions, and catch the exception undetected...What else?Erewhile
Where exactly do we add a password?Pharos
Hi ge0rg, do you have any exemple of your librairies running ? I would like to try it. CheersScribble
@Innards ormlite-android-sqlcipher.jar this jar is not available can you please tell how you made it?Bludge
M
4

How can I use ORMLite with SQLCipher together in Android?

It should be possible @Bruno.

One way that should work is to just copy ORMLite's OrmLiteSqliteOpenHelper class into your project, rename it to LocalOrmLiteSqliteOpenHelper or something, and change the base class to be the SQLCipher helper class. I can't believe they didn't rename the class to be SQLCipherSQLiteOpenHelper. (grumble)

public abstract class LocalOrmLiteSqliteOpenHelper
    extends info.guardianproject.database.sqlcipher.SQLiteOpenHelper {

Another way would be to have your helper extend SQLCipher's SQLiteOpenHelper and then implement the various things you need from OrmLiteSqliteOpenHelper yourself. That would take a bit more work however. ORMLite has to do a little dance with database connections while the database is being created otherwise it goes recursive.

Let me know if either of these work.

Mastectomy answered 7/2, 2012 at 17:30 Comment(3)
I tried it but I am getting compile time errors EX:" new AndroidConnectionSource(this);"Relic
Same error. The constructor AndroidConnectionSource(OrmLiteSqliteOpenHelper) is undefined. Why is this answer accepted?Bebebebeerine
The answer is outdated. It was valid for older versions of ORMLite. So, guys, who are complaining, please hold on while someone will update the answerRue
A
3

Just to update those who need help on this you can copy the entire android source portion of ormlite into your project and change the import of all reference of android's db package to SQLCipher's version.

Basically you have to change all of the package which matches android.database.sqlite to net.sqlcipher.database

For example, from

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

To

import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;

After that put the db password param to the call of getWriteableDatabase in AndroidConnectionSource.java

Anatomical answered 1/11, 2012 at 2:46 Comment(2)
Thanku For your answer.but when i am fetching the data using queryforall() is throwing java.lang.NoSuchMethodError: net.sqlcipher.database.SQLiteDatabase.rawQuery. but i have that method in sqlitedatabase class. how to resolve this any idea???Neuroticism
I did not further explore on this. I stopped using SQLCipher at this moment, can't really help, sorry.Anatomical
M
1

Applying the patch supplied by ge0rg I to found that queryForAll() throws a NoSuchMethod exception. After some investigation I discovered this is a result of rawQuery returning a net.sqlcipher.Cursor and the cursor returned by getQuery (in AndroidCompiledStatement) being an android.database.Cursor. I simply modified AndoridCompiledStatement's imports to:

import net.sqlcipher.Cursor;

And modified getCursor() to return a android.database.Cursor:

public android.database.Cursor getCursor() { ...

With these changes it appears to work for me. Though I'll need to play about a bit more to be completely sure.

Mesial answered 11/12, 2013 at 12:10 Comment(0)
J
1

I know this is quite old thread. But I had to go the same way recently. I've read two threads in search for solution: this and this.

  1. I followed ge0rg's answer, it almost worked, were some problems and I have to replace methods inside my code (I wanted to avoid it).
  2. I did what Eliott Roynette suggested here and it worked good except I needed to add one method to Helper class to accept password and I did it.
  3. I wanted to exclude code into lib to have more smart solution instead of code mix, so I build lib/module separately.

And now I have solution that works (you can clone working demo from GitHub). Placing my answer into both threads to help others in the future.

Jarboe answered 18/9, 2014 at 9:11 Comment(1)
I write my own ORM layer in that project, was more fast and clean.Cattycornered

© 2022 - 2024 — McMap. All rights reserved.