Robolectric で SQL 暗号を使用する際に問題がありますか?
私の回避策は、SQLiteOpenHelper の 2 つの異なる実装を使用することです。1 つは sqlcipher を使用し、もう 1 つはデフォルトのデータベース実装を使用します。これは両方とも、静的なブール値フラグに基づいて SQLiteDatabase を作成するファクトリ クラスの背後にあるため、不確かなデータベース処理は progard から排除されます。
次の問題は、両方が異なる SQLiteDatabase クラスを持っていることです。したがって、SQLiteOpenHelper ラッパーから適切な SQLiteDatabase を使用して作成される SQLiteDatabase のラッパーを再度構築します。Cipher バリアントをベースとして使用します。デフォルトの SQLiteDatabase には存在するが暗号バリアントには存在しないメソッドは無視できます。このラッパー クラスは、同じ静的ブール値フラグを使用して、使用するデータベースを選択します。間違いを犯して間違ったデータベースを取得した場合、ヌルポインタ例外をスローする必要があります;)
アプリ コードでは、ラッパー クラスのみを使用する必要があります。
DatabaseHelper ラッパーの例
public class MyDatabaseHelper {
public static final String DATABASE_NAME = "my.db";
public static final int DATABASE_VERSION = 1;
MyEncryptedDatabaseHelper encryptedDatabase;
MyUnsecureDatabaseHelper unsecureDatabase;
public MyDatabaseHelper(Context context) {
if (ReleaseControl.USE_UNSECURE_DATABASE) {
unsecureDatabase = new MyUnsecureDatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
return;
}
encryptedDatabase = new MyEncryptedDatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public MySQLiteDatabase getWritableDatabase(String password) throws MySQLiteException {
if (ReleaseControl.USE_UNSECURE_DATABASE) {
try {
return new MySQLiteDatabase(unsecureDatabase.getWritableDatabase());
} catch (android.database.SQLException e) {
throw new MySQLiteException(e);
}
}
try {
return new MySQLiteDatabase(encryptedDatabase.getWritableDatabase(password));
} catch (net.sqlcipher.database.SQLiteException e) {
throw new MySQLiteException(e);
}
}
}
および SQLiteDatabase ラッパーからの短いスニペット
public class MySQLiteDatabase {
private net.sqlcipher.database.SQLiteDatabase encryptedDatabase;
private android.database.sqlite.SQLiteDatabase unsecureDatabase;
public MySQLiteDatabase(SQLiteDatabase database) {
encryptedDatabase = database;
}
public MySQLiteDatabase(android.database.sqlite.SQLiteDatabase database) {
unsecureDatabase = database;
}
public static void loadLibs(android.content.Context context) {
if (ReleaseControl.USE_UNSECURE_DATABASE) { return; }
SQLiteDatabase.loadLibs(context);
}
public static int releaseMemory() {
if (ReleaseControl.USE_UNSECURE_DATABASE) {
return android.database.sqlite.SQLiteDatabase.releaseMemory();
}
return net.sqlcipher.database.SQLiteDatabase.releaseMemory();
}
public static SQLiteDatabase openDatabase(String path, String password, MyCursorFactory factory, int flags) {
if(factory == null) factory = new NullCursorFactory();
if (ReleaseControl.USE_UNSECURE_DATABASE) {
return new MySQLiteDatabase(android.database.sqlite.SQLiteDatabase.openDatabase(path, factory.getUnsecure(), flags));
}
return new MySQLiteDatabase(net.sqlcipher.database.SQLiteDatabase.openDatabase(path, password, factory.getEncrypted(), flags));
}
robolectric テストでは、リフレクションごとに USE_UNSECURE_DATABASE を true に設定しました