Используйте отдельную БД для каждого пользователя приложения с 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()
возвращается, и он может когда-нибудь содержать символы, которые недопустимы в именах файлов.
Могу ли я сначала создать поставщика контента после аутентификации пользователя?
Нет извините.
Кажется, что правильным решением здесь является не использовать ContentProvider
s. Поэтому я принял другой ответ.
Но, чтобы ответить на мой актуальный вопрос, для людей, которые решили заставить разные БД работать с одним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
который содержит открытое соединение с БД, инициализируется всякий раз, когда поставщик контента выполняет какое-либо действие с БД, но соединение с БД еще не существует, либо соединение с БД другого пользователя.
Это не правильный способ решения этой проблемы, и в некоторых случаях это может иметь последствия. Но я не хотел оставлять вопрос без ответа.