I am attempting to implement encryption of an Android Room Database using SupportHelper and SupportFactory classes I obtained from Github in conjunction with importing androidx.db.SupportSQLOpenHelper and androidx.sqlite.db.SupportSQLiteDatabase;
The current issue I am getting is a statement as follows:
standardHelper =
new SupportSQLiteOpenHelper(configuration.context, configuration.name,
null, configuration.callback.version, hook) { }
it generates the following error/warning
Class ‘Anynymous class derived from SupportSQLIteOpenHelper’ must either be declared abstract or implement method ‘getDatabaseName() in SupportSQLiteOpenHelper’ (note, it also looks for 3 other methods … close(), getWritableDatabase, getReadableDatabase).
How do I resolve this? Thanks in advance for your assistance
My full SupportHelper class is as follows:
import static androidx.constraintlayout.widget.Constraints.TAG;
import android.content.Context;
import android.database.sqlite.SQLiteException;
import android.util.Log;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
public class SupportHelper implements SupportSQLiteOpenHelper
{
private SupportSQLiteOpenHelper standardHelper;
private byte passphrase;
private final boolean clearPassphrase;
private Context context;
private Context appContext;
private SupportSQLiteDatabase db;
private SupportSQLiteDatabase resultBack;
private SQLiteDatabaseHook hook;
SupportHelper(final SupportSQLiteOpenHelper.Configuration configuration,
byte passphrase, final SQLiteDatabaseHook hook,
boolean clearPassphrase) {
context = configuration.context;
this.passphrase = passphrase;
appContext = context.getApplicationContext();
net.sqlcipher.database.SQLiteDatabase.loadLibs(appContext);
this.clearPassphrase = clearPassphrase;
this.hook = hook;
standardHelper =
new SupportSQLiteOpenHelper(configuration.context, configuration.name,
null, configuration.callback.version, hook) {
public void onCreate(SupportSQLiteDatabase db) {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper onCreate: ");
configuration.callback.onCreate(db);
Log.i(TAG, "CheckingInRoomDatabase SupportHelper onCreate Callback: ");
}
public void onUpgrade(SupportSQLiteDatabase db, int oldVersion,
int newVersion) {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper onUpgrade: ");
configuration.callback.onUpgrade(db, oldVersion,
newVersion);
}
public void onDowngrade(SupportSQLiteDatabase db, int oldVersion,
int newVersion) {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper onDowngrade: ");
configuration.callback.onDowngrade(db, oldVersion,
newVersion);
}
public void onOpen(SupportSQLiteDatabase db) {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper onOpen: ");
configuration.callback.onOpen(db);
}
public void onConfigure(SupportSQLiteDatabase db) {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper onConfigure: ");
configuration.callback.onConfigure(db);
}
};
}
@Override
public String getDatabaseName() {
return standardHelper.getDatabaseName();
}
@Override
public void setWriteAheadLoggingEnabled(boolean enabled) {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper setWriteAheadLoggingEnabled: ");
//standardHelper.setWriteAheadLoggingEnabled(enabled);
Log.i(TAG, "setWriteAheadLoggingEnabled: ");
}
@Override
public SupportSQLiteDatabase getWritableDatabase() {
SupportSQLiteDatabase result;
Log.i(TAG, "CheckingInRoomDatabase SupportHelper getWritableDatabase2: ");
try {
result = standardHelper.getWritableDatabase();
} catch (SQLiteException ex){
if(passphrase != null){
boolean isCleared = true;
for(byte b : passphrase){
isCleared = isCleared && (b == (byte)0);
}
if (isCleared) {
throw new IllegalStateException("The passphrase appears to be cleared. This happens by " +
"default the first time you use the factory to open a database, so we can remove the " +
"cleartext passphrase from memory. If you close the database yourself, please use a " +
"fresh SupportFactory to reopen it. If something else (e.g., Room) closed the " +
"database, and you cannot control that, use SupportFactory boolean constructor option " +
"to opt out of the automatic password clearing step. See the project README for more information.", ex);
}
}
throw ex;
}
if (clearPassphrase && passphrase != null) {
for (int i = 0; i < passphrase.length; i++) {
passphrase[i] = (byte)0;
}
}
resultBack = result;
return result;
}
@Override
public SupportSQLiteDatabase getReadableDatabase() {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper getReadableDatabase: ");
return getWritableDatabase();
}
@Override
public void close() {
Log.i(TAG, "CheckingInRoomDatabase SupportHelper close: ");
standardHelper.close();
}
}
My full Support factory classs is as follows
import androidx.sqlite.db.SupportSQLiteOpenHelper;
public class SupportFactory implements SupportSQLiteOpenHelper.Factory {
private final byte passphrase;
private final SQLiteDatabaseHook hook;
private final boolean clearPassphrase;
public SupportFactory(byte[] passphrase) {
this(passphrase, (SQLiteDatabaseHook)null);
}
public SupportFactory(byte[] passphrase, SQLiteDatabaseHook hook) {
this(passphrase, hook, true);
}
public SupportFactory(byte[] passphrase, SQLiteDatabaseHook hook,
boolean clearPassphrase) {
this.passphrase = passphrase;
this.hook = hook;
this.clearPassphrase = clearPassphrase;
}
@Override
public SupportSQLiteOpenHelper create(SupportSQLiteOpenHelper.Configuration configuration) {
return new SupportHelper(configuration, passphrase, hook, clearPassphrase);
}
}