将 android.database.sqlite.SQLiteOpenHelper 更改为 net.sqlcipher.database.SQLiteOpenHelper 后未调用 onUpgrade 和 onCreate

onUpgrade and onCreate not being called after changing android.database.sqlite.SQLiteOpenHelper to net.sqlcipher.database.SQLiteOpenHelper

我一直在关注 official documentation 以便开始在我开发的应用程序中使用 SQLCipher Community Edition。所以,我做了一个正确的 gradle 导入如下:

compile 'net.zetetic:android-database-sqlcipher:3.5.9@aar'

我添加了

@Override
public void onCreate() {
   super.onCreate();
   SQLiteDatabase.loadLibs(this);
}

在MainApplication.java。 由于我的应用程序已经发布,我还在我的 SQLiteOpenHelper class 实例的 onUpgrade() 方法中放置了一些迁移代码。 不幸的是,虽然我升级了数据库版本号,但我还是调用了: getInstance().getReadableDatabase("testKey"); onUpgrade() 和 onCreate() 方法都不会被调用。 我是否遗漏了配置中的某些内容?

如果您是第一次在之前的 non-ciphered 数据库中使用密码,那么我建议您将数据库强制设置为 re-created。

为此,您只需在 DatabaseHelper class 中更改数据库名称即可。更改数据库名称后,当您的设备更新时,将触发 onCreate() 并从零开始创建您的所有数据库。

public class YourDatabaseHelper extends SQLiteOpenHelper {

   public final static String DATABASE_NAME = Constants.DATABASE_NAME; // Change the name to force the database to be created from zero.
   public final static int CURRENT_VERSION = Constants.DATABASE_VERSION_INT;


   public DatabaseHelper(Context context){
       super(context, DATABASE_NAME, null, CURRENT_VERSION);        
   }

   public void onCreate(SQLiteDatabase db){
       // Create all your tables.
   }

   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
       // No need to do anything in here, because onCreate will be triggered.
   }

}

终于找到了解决问题的方法。我没有在 onUpgrade() 方法中调用迁移功能,而是在第一次查询数据库之前(打开应用程序后)添加了迁移代码:

public static void encrypt(Context ctxt, File originalFile, char[] 
passphrase)
throws IOException {
SQLiteDatabase.loadLibs(ctxt);

if (originalFile.exists()) {
  File newFile=
  File.createTempFile("sqlcipherutils", "tmp", ctxt.getCacheDir());
   SQLiteDatabase db=
   SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(), "", null, SQLiteDatabase.OPEN_READWRITE);

   db.rawExecSQL("ATTACH DATABASE '" + newFile.getAbsolutePath()+ "' AS encrypted KEY '"+String.valueOf(passphrase)+"'");
   db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
   db.rawExecSQL("DETACH DATABASE encrypted");

   int version=db.getVersion();

    db.close();

    db=SQLiteDatabase.openDatabase(newFile.getAbsolutePath(), passphrase, null, SQLiteDatabase.OPEN_READWRITE);
    db.setVersion(version);
    db.close();

    originalFile.delete();
    newFile.renameTo(originalFile);
  }
}

我从这个 source 中得到了解决方案。感谢作者,不管他是谁!