我该如何在Android中同时使用ORMLite和SQLCipher?

16

我想在我的Android项目中使用OrmLiteSQLCipher,但这两个库都有各自的抽象SQLiteOpenHelper类需要实现。Java不允许一个类继承两个类,如果我分别实现它们,它们将无法相互通信。

我该如何同时使用它们?如何解决SQLiteOpenHelper实现的问题?


SQLCipher的版本是SQLiteOpenHelper的重构版本,也就是说它不是同一个类。为了让这两个类能够很好地协作,你需要重新设计整个OrmLite库,使用SQLCipher包代替原来的包。 - Jens
1
如果OrmLite可以直接实现这个功能,那就太棒了。而且如果SqlCipher能以Maven构件的形式提供,那就更好了。它们似乎是两个明显需要更好地协同工作的库。 - Adam Mackler
5个回答

6

我将Rejinderi的答案提炼为一个ORMLite 4.43补丁,并编译成JAR文件。按照以下步骤将其集成到Android项目中:

  1. 按照SQLCipher for Android HOWTO获取SQLCipher到您的项目中
  2. 将ORMLite添加到您的项目中(请参见如何在Android中使用ORMLite和SQLite的好教程
  3. ormlite-android-sqlcipher.jar替换libs/ormlite-android.jar
  4. 将您的私密数据库密码添加到适当的DB打开方法中

但是,您不应该相信我提供的未经操纵的JAR文件,请按照补丁中的构建说明进行操作。

编辑:使用补丁过的库,需要将对getReadableDatabase()getWritableDatabase()OrmLiteSqliteOpenHelper构造函数的调用添加额外的密码参数。如果您正在使用DB helper,请适当扩展它以将密码传递给OrmLiteSqliteOpenHelper。


是的?你的数据库密码是什么? :) - stephen
我的密码是“password”;但我所说的是我提供的JAR文件可能也包含一个sendCovertMessageTo("ge0rg", your_db_password)的行... - ge0rg
1
我没想到你会回答那个问题。我猜这证明了你的观点。如果它与原始文件大小相同,你会在哪里找到资源/手段将信息发送到某个地方?我真的很好奇。我对Dalvik上的安全性有兴趣,但了解甚少。 - stephen
我猜你可以假设应用程序权限,并捕获未检测到的异常...还有什么? - stephen
我们应该在哪里添加密码? - John Baum
显示剩余2条评论

4
我该如何在Android中同时使用ORMLite和SQLCipher?
@Bruno,这应该是可行的。
一种可能的方法是将 ORMLite的OrmLiteSqliteOpenHelper复制到您的项目中,将其重命名为LocalOrmLiteSqliteOpenHelper或其他名称,并更改基类为SQLCipher帮助类。我无法相信他们没有将该类重命名为SQLCipherSQLiteOpenHelper。(抱怨)
public abstract class LocalOrmLiteSqliteOpenHelper
    extends info.guardianproject.database.sqlcipher.SQLiteOpenHelper {

另一种方法是让您的助手扩展SQLCipher的SQLiteOpenHelper,然后自己实现您需要的各种内容OrmLiteSqliteOpenHelper。但这需要更多的工作。ORMlite必须在创建数据库时执行一些与数据库连接相关的操作,否则会出现递归问题。
如果这两种方法都可以,请告诉我。

3
我尝试了一下,但是编译时出现了错误,例如:"new AndroidConnectionSource(this);"。 - Bhaskar Reddy
1
相同的错误。构造函数AndroidConnectionSource(OrmLiteSqliteOpenHelper)未定义。为什么这个答案被接受了? - Jesse Jin
2
答案已经过时了。它适用于旧版本的ORMLite。所以,那些抱怨的人,请稍等,直到有人更新答案。 - Eugen Martynov

3

想要帮助的人更新一下,你可以将ormlite的整个android源代码部分复制到你的项目中,并将所有对于android数据库包的引用改为SQLCipher的版本。

基本上你需要将所有匹配android.database.sqlite的包都改为net.sqlcipher.database

例如,从:

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

To

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

在AndroidConnectionSource.java中调用getWriteableDatabase时,请将数据库密码参数放入其中。

谢谢您的回答。但是,当我使用queryforall()获取数据时,它会抛出java.lang.NoSuchMethodError: net.sqlcipher.database.SQLiteDatabase.rawQuery错误。但是我在sqlitedatabase类中有该方法。有什么解决办法吗? - Roster
我没有进一步探索这个问题。我暂时停止使用SQLCipher,不能提供帮助,抱歉。 - Rejinderi

1

应用ge0rg提供的补丁后,我发现queryForAll()会抛出一个NoSuchMethod exception。经过一番调查,我发现这是由于rawQuery返回了一个net.sqlcipher.Cursor,而getQuery(在AndroidCompiledStatement中)返回的游标是一个android.database.Cursor。我只需修改AndroidCompiledStatement的导入即可:

import net.sqlcipher.Cursor;

并将getCursor()修改为返回android.database.Cursor:

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

通过这些更改,它对我来说似乎可以工作。虽然我需要再多玩一会儿才能完全确定。


1

我知道这是一个相当旧的帖子。但最近我也不得不走同样的路。我阅读了两个帖子寻找解决方案: thisthis

  1. 我遵循了ge0rg的 答案,它几乎起作用了,但有些问题,我不得不替换代码中的一些方法(我想避免这种情况)。
  2. 我按照Eliott Roynette的建议做了这里,它运行良好,除了需要向Helper类添加一个接受密码的方法,我已经完成了。
  3. 我想将代码排除到lib中,以拥有更智能的解决方案,而不是混合代码,因此我单独构建了lib/module。

现在我有一个solution可以工作(您可以从GitHub克隆工作演示)。将我的答案放入两个线程中,以帮助未来的其他人。


我在那个项目中编写了自己的ORM层,更快更干净。 - Bruno Nardini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接