2012-05-19 12 views
14

Pracuję nad aplikacją dla systemu Android, gdzie użyłem istniejącej bazy danych sqlite w folderze zasobów. Więc faktycznie kopiuję bazę danych z tego folderu. Użytkownik może również zapisywać własne dane (zaznaczyć dowolną treść jako ulubioną).Sqlite database onUpgrade() nie jest wywoływana

Przesłałem wersję na rynek. Teraz chcę dodać kilka nowych danych do bazy danych i załadować nową wersję. Jeśli użytkownik zaktualizuje aplikację z rynku, chcę zachować dane użytkownika (z poprzedniej wersji) i dodać nowe dane. Zrobiłem trochę google i okazało się, że w metodzie aktualizacji powinno załatwić sprawę. Ale zmieniam DATABASE_VERSION z kodu, ale metoda aktualizacji nie otrzyma połączenia. Zastanawiam się, że coś przeoczyłem. Tu jest mój kodu:

public class DataBaseHelper extends SQLiteOpenHelper { 

private static String DB_PATH = "/data/data/riskycoder.login/databases/"; 
public static String DB_NAME = "datenbank_EN.sqlite"; 
private SQLiteDatabase myDataBase; 
private final Context myContext; 
private static final int DATABASE_VERSION = 1; 





public DataBaseHelper(Context context) { 
    super(context, DB_NAME, null, DATABASE_VERSION); 
    this.myContext = context; 
} 

public void createDataBase() throws IOException { 
    boolean dbExist = checkDataBase(); 
    if (dbExist) { 
    } else { 
     this.getWritableDatabase(); 
     try { 
      this.close(); 
      copyDataBase(); 
     } catch (IOException e) { 
      throw new Error("Error copying database"); 
     } 
    } 

} 

private boolean checkDataBase() { 
    SQLiteDatabase checkDB = null; 
    try { 
     String myPath = DB_PATH + DB_NAME; 
     checkDB = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READWRITE); 
    } catch (SQLiteException e) { 
    } 
    if (checkDB != null) 
     checkDB.close(); 
    return checkDB != null ? true : false; 
} 

private void copyDataBase() throws IOException { 

    InputStream myInput = myContext.getAssets().open(DB_NAME); 
    String outFileName = DB_PATH + DB_NAME; 
    OutputStream myOutput = new FileOutputStream(outFileName); 
    byte[] buffer = new byte[2048]; 
    int length; 
    while ((length = myInput.read(buffer)) > 0) { 
     myOutput.write(buffer, 0, length); 
    } 
    myOutput.flush(); 
    myOutput.close(); 
    myInput.close(); 

    //myDataBase.setVersion(DATABASE_VERSION); 
} 

public void openDataBase() throws SQLException { 
    String myPath = DB_PATH + DB_NAME; 
    myDataBase = SQLiteDatabase.openDatabase(myPath, null,SQLiteDatabase.OPEN_READWRITE); 
    Log.d("Test", "Database version: " +myDataBase.getVersion()); 
} 

@Override 
public synchronized void close() { 
    if (myDataBase != null) 
     myDataBase.close(); 
    super.close(); 
} 



@Override 
public void onCreate(SQLiteDatabase db) { 
} 

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    Log.d("Test", "in onUpgrade. Old is: " + oldVersion + " New is: " + newVersion); 


} 

}

+0

* Zmieniam DATABASE_VERSION z kodu .. *, co to dokładnie oznacza? Widzę, że nazywasz super konstruktora 'SQLiteOpenHelper' ze stałym polem' DATABASE_VERSION' (którego oczywiście nie można zmienić), więc jak dokładnie zmieniasz wersję bazy danych? – Luksprog

+0

W nowej wersji aplikacji zmieniłem DATABASE_VERSION na 2. Tak więc podczas instalacji nowej wersji powinna zostać wywołana metoda onUpgrade. Czy czegoś mi brakuje? – rawcoder064

+0

Po pierwsze, kod, który wysłałeś showa DATABASE_VERSION ma wartość 1, więc funkcja onUpgrade nie zostanie wywołana.Po drugie, nawet jeśli był 2, twoja funkcja onUpgrade nie ma kodu, który można zrobić, aby zaktualizować bazę danych. Nie dzieje się to automatycznie, musisz to zrobić. – Barak

Odpowiedz

18

onUpgrade() nazywa się tylko wtedy, gdy zmiany w bazie danych numer wersji został wykryty. Przyrost wersję bazy danych w następujący sposób:

private static final int DATABASE_VERSION = 2; 
+0

Nie zrobi mu to zbyt dobrze, ponieważ wszystkie operacje onUpgrade są wypluwane z logu (przynajmniej z opublikowanym kodem) – Barak

+1

OP zadał pytanie "dlaczego nie wywołuje metody 'onUpgrade'." Oczywiście wypisze tylko komunikat dziennika, ponieważ nie zaimplementował jeszcze 'onUpgrade'. –

+0

@ AlexLockwood-> Zmieniłem DATABASE_VERSION na 2, tak jak powiedziałeś, ale nic nie zostało pokazane na wyjściu logcat. Stworzyłem bazę danych przez przeglądarkę sqlite. Czy powinienem wykonać jakąkolwiek wersję podczas tworzenia bazy danych? – rawcoder064

2

Spróbuj tego (zwiększenie Database_Version) & onUpdate() zostanie wywołana:

private static final int DATABASE_VERSION = 2; 
+0

To będzie nazywane i nic nie robić ... – Barak

+0

@ Barak-> Umieściłem instrukcję log.d w onUpgrade() do przetestowania. Ale nic nie widzę w wynikach logcat. Oznacza to, że funkcja onUpgrade nie zostanie wywołana. W metodzie openDataBase() umieściłem instrukcję log.d. Widzę, że wersja bazy danych jest zawsze 1, nawet jeśli zmienię DATABASE_VERSION na 2. – rawcoder064

2

Zakładając, że nie zmieni Database_Version, trzeba jeszcze umieścić kod w ONUPGRADE aby tak się stało. To nie jest magiczne, musisz powiedzieć, co robić.

W twoim przypadku trzeba:

1) kopia starej bazy (nadać mu nową nazwę)
2) skopiuj do nowej bazy danych
3) odczytać dane ze starej bazy danych
4) kopia żadnych różnic w nowej bazie danych
5) usunąć stare bazy

EDIT

Zakładając, że statek DB w aktywach folderu należy skopiować go do użytku tak:

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    // First copy old db 
    InputStream bakInput = getActivity().getAssets().open(dbname); 
    String bakFileName = getActivity().getAssets() + "YourDB.old"; 
    OutputStream bakOutput = new FileOutputStream(bakFileName); 
    byte[] buffer = new byte[1024]; 
    int length; 
    while ((length = bakInput.read(buffer)) > 0) { 
     bakOutput.write(buffer, 0, length); 
    } 
    myOutput.flush(); 
    myOutput.close(); 
    myInput.close(); 

    // delete the old db 
    File delDB = new File(getActivity().getAssets() + "YourDB"); 
    boolean deleted = file.delete(); 

    // Copy in the new db 
    InputStream myInput = getActivity().getAssets().open("YourDB"); 
    String outFileName = MAIN_DB_PATH + dbname; 
    OutputStream myOutput = new FileOutputStream(outFileName); 
    byte[] buffer = new byte[1024]; 
    int length; 
    while ((length = myInput.read(buffer)) > 0) { 
     myOutput.write(buffer, 0, length); 
    } 
    myOutput.flush(); 
    myOutput.close(); 
    myInput.close(); 

    // add code here to get changes user has made to db and move them to updated db 

    // delete the old db copy 
    File delDB = new File(getActivity().getAssets() + "YourDB.old"); 
    boolean deleted = file.delete(); 
} 
+0

Przepraszam, ale cię nie dostałem. W moim przypadku w jaki sposób mogę skopiować nową bazę danych. Czy możesz napisać jakiś kod, jak to zrobić ... Przepraszam za moje głupie pytanie ... – rawcoder064

+0

@Barak możesz mi pomóc, moja metoda onUpgrade nie jest nazywana – Erum

6

Zmień ONUPGRADE z następującym

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

      if(newVersion > oldVersion){      
        myContext.deleteDatabase(DB_NAME); 
      } 
     } 

A także zmienić createDatabase() jak poniżej,

public void createDataBase() throws IOException{ 

      boolean dbExist = checkDataBase(); 

      if(dbExist){ 
       // By calling this method here onUpgrade will be called on a 
       // writable database, but only if the version number has been increased 

       this.getWritableDatabase(); 
      } 

      dbExist = checkDataBase(); 

      if(!dbExist){ 

       //By calling this method an empty database will be created into the      default system path 
        //of the application so we will be able to overwrite that database with our database. 
       this.getReadableDatabase(); 

       try { 

        copyDataBase(); 

       } catch (IOException e) { 

        throw new Error("Error copying database"); 

       } 
      } 

     } 

Na koniec zwiększ swoją wersję bazy danych i uruchom ją ponownie. onUpgrade nie zostanie wywołany, dopóki nie zadzwonisz pod numer getReadableDatabase() lub podobne funkcje.

Mam nadzieję, że to pomoże

+0

Podążyłem za twoją odpowiedzią, ale wciąż moja onUpgrade metoda nie jest wywoływana, możesz mi pomóc – Erum

Powiązane problemy