Используйте отдельную БД для каждого пользователя приложения с SQLiteOpenHelper и ContentProvider

Мое приложение использует базу данных SQLite, обернутую SQLiteOpenHelper и ContentProvider, Я добавил функцию входа в приложение и теперь хочу, чтобы каждый пользователь мог видеть только свои данные. Я подумал, как добиться этого, чтобы приложение создавало отдельную БД для каждого пользователя, который входит в приложение, и использовал идентификатор пользователя в имени файла базы данных.

у меня есть это ContentProvider:

public class MyProvider extends ContentProvider {

    //...

    @Override
    public boolean onCreate() {
    dbHelper = new MyDBHelper(getContext());
    return true;
}

у меня есть это SQLiteOpenHelper:

public class MyDBHelper extends SQLiteOpenHelper {

У которого есть этот конструктор:

public MyDBHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
}

До сих пор в приложении не было нескольких пользователей, поэтому у него была только одна база данных. так DB_NAME всегда была одна и та же строка. Теперь я попытался установить это так:

private static String UID = FirebaseAuth.getInstance().getCurrentUser().getUid();
public static final String DB_NAME = String.format("data%s.db", UID);

(Как видите, я использую Firebase Аутентификация)

но это привело к сбою, поскольку, по-видимому, поставщик контента создается при запуске приложения до того, как пользователь прошел аутентификацию. (так user нулевой. Да, я должен проверить это user не является нулевым, прежде чем я пытаюсь позвонить getUid(), но это не заставит эту вещь работать)

Так что это не похоже на правильный подход. Как я могу использовать другую БД в соответствии с подписанным пользователем? Могу ли я сначала создать поставщика контента после аутентификации пользователя?

Я также мог бы просто сохранить все в одной базе данных и добавить UID колонка. Но будет ли это достаточно хорошо защищать данные разных пользователей друг от друга? Кроме того, это будет означать гораздо больше изменений кода.

2 ответа

Решение

Как я могу использовать другую БД в соответствии с подписанным пользователем?

Простое решение состоит в том, чтобы избавиться от ContentProvider, Единственная причина использовать ContentProvider если вы собираетесь передавать эти данные другим приложениям.

Кроме того, я бы с осторожностью принял getUid() и положить его в имя файла. Вы не контролируете то, что getUid() возвращается, и он может когда-нибудь содержать символы, которые недопустимы в именах файлов.

Могу ли я сначала создать поставщика контента после аутентификации пользователя?

Нет извините.

Кажется, что правильным решением здесь является не использовать ContentProviders. Поэтому я принял другой ответ.

Но, чтобы ответить на мой актуальный вопрос, для людей, которые решили заставить разные БД работать с однимContentProviderВот как это можно сделать:

Я изменил обычай SQLiteOpenDBHelperконструктор также взять uid:

    public MyDBHelper(Context context, String uid) {
        super(context, String.format(DB_NAME, uid), null, DB_VERSION);
        UID = uid;
    }

и я изменил onCreate из моего ContentProvider не создавать DBHelper, Я создал эту функцию, которая инициализирует DBHelper вместо:

    public void initDB(Uri uri) {
        String uid = uri.getPathSegments().get(0);
        if (dbHelper == null){
            dbHelper = new MyDBHelper(getContext(), uid);
        } else if (!uid.equals(dbHelper.UID)){
            dbHelper.close();
            dbHelper = new MyDBHelper(getContext(), uid);
        }
    }

и я называю этот метод в начале query, insert, update а также delete методы.

Итак DBHelper который содержит открытое соединение с БД, инициализируется всякий раз, когда поставщик контента выполняет какое-либо действие с БД, но соединение с БД еще не существует, либо соединение с БД другого пользователя.

Это не правильный способ решения этой проблемы, и в некоторых случаях это может иметь последствия. Но я не хотел оставлять вопрос без ответа.

Другие вопросы по тегам