Issues with SupportSQLiteOpenHelper syntax

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);
}

}


Hi @grgmobile,

Thank you for your interest in SQLCipher. Both SQLCipher for Android [1], and SQLCipher for Android legacy edition [2] contain SupportHelper implementations which you can use to integrate directly with the Room API.


  1. sqlcipher-android/SupportHelper.java at master · sqlcipher/sqlcipher-android · GitHub ↩︎

  2. android-database-sqlcipher/SupportHelper.java at master · sqlcipher/android-database-sqlcipher · GitHub ↩︎

1 Like

Thanks, I replaced my code with your different versions from Github.

It does not like the constructor for openHelper = new SQLiteOpenHelper(configuration.context, configuration.name, password, null, configuration.callback.version, minimumSupportedVersion, null, hook, enableWriteAheadLogging)

Hi @grgmobile,

Which SQLCipher for Android library are you using? There are examples within the GitHub repositories for usage. We would need to know if you are using the new or legacy edition of the library (i.e., sqlcipher-android, or android-database-sqlcipher respectively) in order to provide further direction.

Thees are the imports from the example you identified off GitHub. It is a new implementation, so unless there is a reason not to, I would prefer to use new libraries and not a legacy version. Thanks again for your help.

import androidx.annotation.Nullable;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;

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

Hi @grgmobile,

The sqlcipher-android library [1] contains a test suite which you might find useful. An example of using the Room API with SQLCipher can be found here [2].


  1. GitHub - sqlcipher/sqlcipher-android: SQLCipher for Android provides an interface to SQLCipher databases on the Android platform. ↩︎

  2. sqlcipher-android/RoomUpsertTest.java at master · sqlcipher/sqlcipher-android · GitHub ↩︎