Zgodnie z komentarzem Gabe Sechan, najprostszą metodą byłoby skopiowanie bazy danych z folderu zasobów przy każdym uruchomieniu aplikacji, czyli zmiana :-
private void createDB(){
boolean dbExist = DBExists();
if(!dbExist){
this.getReadableDatabase();
copyDBFromResource();
}
dbSglite=getReadableDatabase();
}
do :-
private void createDB(){
copyDBFromResource();
dbSglite=getReadableDatabase();
}
Najwyraźniej masz wątpliwości, komentując
„Czy nie byłoby to kopiowanie bazy danych za każdym razem, gdy rozpoczyna się aktywność?”
tak, to by (czy to byłoby aż tak złe? - retoryczne ).
Załóżmy jednak, że miałeś użyć wersji bazy danych, tj. Porównać wersję w folderze zasobów z bieżącą wersją. Zasadniczo nadal potrzebujesz dostępu do bazy danych z folderu zasobów, więc porównujesz jedną bazę danych z drugą (przynajmniej otwierając je). Więc nadal będzie trochę kosztów ogólnych.
Opcją, która może być mniej intensywna, jest sprawdzenie ostatniej modyfikacji pliku zasobu data z datą ostatniego skopiowanego pliku zasobu we wspólnych preferencjach. (File
lastModified
metoda) Plik - lastModified.
Inną opcją, z podobnego punktu widzenia, byłoby sprawdzenie wersji pakietu w stosunku do ostatnio zaimplementowanej, ponownie przechowywanej we wspólnych preferencjach.PackageInfo - versionCode.
Oczywiście w obu tych opcjach zastąpienie bazy danych z pliku zasobów ma miejsce tylko wtedy, gdy jest różnica (wzrost).
Przykład użycia wersji pakietu
Poniższy przykład (wszystkie zmiany w dbHelper class) skopiuje bazę danych z zasobów, jeśli wersja pakietu zostanie zwiększona (lub jeśli baza danych nie istnieje) :-
class dbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "questions.db";
private static final int SCHEMA_VERSION = 1;
private static final String SHARED_PREFS = "shared_prefs";
private static final String SHARED_PREFKEY_QUESTIONSDBLASTUPDATED = "spkey_qdblastupdated";
public SQLiteDatabase dbSglite;
private String mDBPath;
private final Context myContext;
public dbHelper(Context context) {
super(context, DATABASE_NAME, null, SCHEMA_VERSION);
this.myContext=context;
this.mDBPath=context.getDatabasePath(DATABASE_NAME).getParent();
}
@Override
public void onCreate(SQLiteDatabase db){
Log.d("ONCREATE","OnCreate Method Called.");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void createDatabase(){
createDB();
}
private void createDB(){
if (isQuestionsDBNew() || (!DBExists())) {
Log.d("COPYFROMASSET", "Copying Questions From Assets");
copyDBFromResource();
setQuestionsDBNew(getPackageVersion());
} else {
Log.d("COPYFROMASSET",
"Questions not copied from Assets - New Questions Check result was " +
Boolean.toString(isQuestionsDBNew()) +
" DB Exists result was " + Boolean.toString(DBExists())
);
}
dbSglite=getReadableDatabase();
}
private boolean DBExists(){
SQLiteDatabase db = null;
try {
String databasePath = myContext.getDatabasePath(DATABASE_NAME).getPath();
db = SQLiteDatabase.openDatabase(databasePath,null, SQLiteDatabase.OPEN_READWRITE);
db.setLocale(Locale.getDefault());
db.setLockingEnabled(true);
db.setVersion(1);
} catch (SQLiteException e) {
Log.e("SqlHelper", "database not found");
}
if (db != null) {
db.close();
}
return db != null;
}
private void copyDBFromResource() {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = myContext.getAssets().open(DATABASE_NAME);
File databasedir = new File(myContext.getDatabasePath(DATABASE_NAME).getParent());
databasedir.mkdirs();
outputStream = new FileOutputStream(mDBPath+"/"+DATABASE_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0){
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
throw new Error("Problem copying database.");
}
}
public void openDataBase() throws SQLException {
String myPath = myContext.getDatabasePath(DATABASE_NAME).getPath();
dbSglite = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
}
private boolean isQuestionsDBNew() {
SharedPreferences prefs = myContext.getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE);
long stored_lastused = prefs.getLong(SHARED_PREFKEY_QUESTIONSDBLASTUPDATED,-1);
Log.d("NEWQUESTIONS?", "Result of testing package version " +
String.valueOf(stored_lastused) +
" against " +
String.valueOf( getPackageVersion()) +
" was " + String.valueOf(stored_lastused < getPackageVersion()));
return (stored_lastused < getPackageVersion());
}
private long getPackageVersion() {
PackageInfo pi;
try {
pi = myContext.getPackageManager().getPackageInfo(myContext.getPackageName(),0);
} catch (PackageManager.NameNotFoundException e) {
return -1;
}
Log.d("PACKAGEVERSION", "The version of package " +
myContext.getPackageName() +
" was " +
String.valueOf(pi.versionCode)
);
return pi.versionCode;
}
private void setQuestionsDBNew(long lastused) {
SharedPreferences.Editor editor = myContext.getSharedPreferences(SHARED_PREFS, Context.MODE_PRIVATE).edit();
editor.putLong(SHARED_PREFKEY_QUESTIONSDBLASTUPDATED,lastused);
editor.apply();
}
}
Notatki
- Kod jest w dużej mierze oparty na kodzie z pytania. Są :-
- Dwie dodatkowe zmienne klasy (stałe) do obsługi wspólnych preferencji.
- Trzy nowe metody:-
isQuestionsDBNew
to zwraca prawdę, jeśli wersja pakietu jest większa niż wersja przechowywana we wspólnych preferencjach (nic we wspólnych preferencjach nie daje -1, więc powinno być mniejsze niż jakakolwiek wersja pakietu).getPackageVersion
zwraca wersję pakietu jako długą.setQuestionsDBNew
który aktualizuje odpowiednie wspólne preferencje.- Zmiany w createDB w celu sprawdzenia zmiany wersji pakietu, a następnie skopiowania bazy danych z zasobów. Istnieje dodatkowe sprawdzenie, czy baza danych istnieje, chociaż byłoby to potrzebne tylko w przypadku usunięcia samego pliku bazy danych. Usunięcie danych aplikacji spowoduje usunięcie wspólnych preferencji, co spowoduje skopiowanie bazy danych.
- Kod zawiera pewne rejestry diagnostyczne, które zostawiłem.
- To nie zostało gruntownie przetestowane (tj. nie poszedłem w zakresie zwiększania wersji pakietu).
Wyjście z przykładu — instalowana aplikacja :-
01-05 19:46:44.849 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/NEWQUESTIONS?: Result of testing package version -1 against 1 was true
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:46:44.850 26692-26692/m.com.so48103235_updateprepopdb D/COPYFROMASSET: Copying Questions From Assets
01-05 19:46:44.855 26692-26692/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
Wyjście z przykładu - Kolejne uruchomienie :-
01-05 19:48:10.375 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.376 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.376 26755-26755/m.com.so48103235_updateprepopdb D/NEWQUESTIONS?: Result of testing package version 1 against 1 was false
01-05 19:48:10.376 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.381 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.381 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.381 26755-26755/m.com.so48103235_updateprepopdb D/NEWQUESTIONS?: Result of testing package version 1 against 1 was false
01-05 19:48:10.382 26755-26755/m.com.so48103235_updateprepopdb D/PACKAGEVERSION: The version of package m.com.so48103235_updateprepopdb was 1
01-05 19:48:10.387 26755-26755/m.com.so48103235_updateprepopdb D/COPYFROMASSET: Questions not copied from Assets - New Questions Check result was false DB Exists result was true
- Dodatkowe komunikaty ze względu na bardziej obszerny komunikat używany podczas zgłaszania, że baza danych nie została skopiowana, wywołując ponownie metody, które dodają komunikaty dziennika.