2017-04-04 28 views
13

Mam aplikację z bazą danych, utworzoną i otwartą przy użyciu standardowego SQLiteOpenHelper.Nie mogę obniżyć wersji bazy danych z wersji `n` na` n-1` na Samsunga

Ilekroć aktualizuję wersję bazy danych, aktualizuję również kod wersji aplikacji, więc nie ma możliwości, aby baza danych uległa zmniejszeniu (numer wersji bazy danych jest zawsze zwiększany, nigdy nie zmniejszany).

Wyłączyłem kopię zapasową bazy danych w mojej aplikacji, ustawiając właściwość android:allowBackup na wartość false.

Ale kiedy uaktualnić aplikację w Sklepie Play, dostaję dużo katastrofie

Nie można obniżyć bazę danych z wersji n do n-1

96% osób w katastrofie występują na Działające urządzenie Samsung. Ktoś wie, dlaczego występuje ten problem, a co ważniejsze, jak temu zapobiec?

Wiem, że mogę przesłonić onDowngrade, aby zapobiec awarii, ale tak naprawdę nie rozumiem, dlaczego onDowngrade jest wywoływana w ogóle, ponieważ awarię wywołuje się w aplikacji, która zawsze używa ostatniej wersji bazy danych.

Edit: Dodano przykładowy kod, FWIW

Moja OpenHelper:

public class MyDBHelper extends SQLiteOpenHelper { 

    private static final String LOG_TAG = MyDBHelper.class.getName(); 

    public static final String DB_NAME = "my_db"; 
    public static final int DB_V1 = 1; 
    public static final int DB_V2_UNIQUE_IDS = 2; 
    public static final int DB_V3_METADATAS = 3; 
    public static final int DB_V4_CORRUPTED_IDS = 4; 
    public static final int DB_V5_USAGE_TABLE = 5; 

    public static final int DB_VERSION = DB_V5_USAGE_TABLE; 

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

    @Override 
    public void onCreate(final SQLiteDatabase db) { 
     Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onCreate()"); 
     db.execSQL(createMyTable()); 
    } 

    @Override 
    public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { 
     Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onUpgrade(): oldVersion = " + oldVersion + " : newVersion = " + newVersion); 

     if (oldVersion < 2) { 
      Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onUpgrade(): upgrading version 1 table to version 2"); 
      db.execSQL(upgradeTable_v1_to_v2()); 
     } 

     if (oldVersion < 3) { 
      Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onUpgrade(): upgrading version 2 Entry table to version 3"); 
      db.execSQL(upgradeTable_v2_to_v3()); 
     } 
    } 

    @Override 
    @TargetApi(Build.VERSION_CODES.FROYO) 
    public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { 
     Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onDowngrade(): oldVersion = " + oldVersion + " : newVersion = " + newVersion); 
     super.onDowngrade(db, oldVersion, newVersion); 
    } 
} 

A jak ja go zainicjować:

public class DatabaseController { 

    private MyDBHelper mDBHelper; 

    public void initialize(final Context context) { 

     mDBHelper = new MyDBHelper(context); 

    } 
} 
+0

Czy jesteś w stanie zobaczyć, czy te awarie pochodzą z urządzeń zrootowanych? na urządzeniach zrootowanych użytkownicy mogą zdegradować aplikacje, jeśli zdecydują się na – marmor

+0

99,9% urządzenia nie jest zrootowanych. – XGouchet

+1

czy może używasz 'SQLiteOpenHelper' z parametrem wersji gdzieś w projekcie? Jeśli nadpisujesz 'SQLiteOpenHelper', upewnij się, że wywołujesz super w konstruktorze z najnowszą wersją – marmor

Odpowiedz

6

Jest to domyślna implementacja z SQLiteOpenHelper.onDowngrade(...):

public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    throw new SQLiteException("Can't downgrade database from version " + 
      oldVersion + " to " + newVersion); 
} 

Jak widzisz, zadzwoń pod super.onDowngrade(...), tak jak ty, dostaniesz wyjątek. Musisz sam wdrożyć onDowngrade, nie dzwoniąc pod numer super.onDowngrade. Zawsze należy go wprowadzać w życie, ponieważ nie ma gwarancji, że można go nazwać - brzmi to dziwnie, że użytkownik zmienił się, aby korzystać ze starszej wersji aplikacji, ale może się zdarzyć taka sytuacja. Czy wiesz, z której wersji aplikacji pochodzą wyjątki?

+0

To było tak oczywiste, że nawet nie zauważyłem połączenia z super metodą ... Uwaga: Pytanie na końcu nie jest konieczne, aby obniżyć poziom DB (z jakiegokolwiek powodu), należy to zaimplementować, tak samo dla uaktualnienie. – AxelH

+0

Jeśli przeczytałeś moje pytanie, powiedziałem, że wiem, że mogę przesłonić metodę onDowngrade. Moje pytanie dotyczyło przyczyny, dla której została wybrana opcja onDowngrade bez żadnego powodu! – XGouchet

+0

Czy widzisz, z której wersji aplikacji pochodzą te awarie? To może dać ci wskazówkę - jeśli jest to najnowsza wersja, system robi coś dziwnego. – etan

0

Komentarz odpowiedź @etan:

dlaczego onDowngrade nazwano bez żadnego powodu?

Istnieje bezwzględny powód,

public static final int DB_V5_USAGE_TABLE = 5; 

public static final int DB_VERSION = DB_V5_USAGE_TABLE; 

swój DB_VERSION posiada 5 i konstruktora, trzeba przejechać tę wartość. Oczywiście argument dla wersji powinien być większy niż poprzednia wersja, w przeciwnym razie otrzymasz tę wiadomość.

Jak wyrażono przez @etan, jeśli chcesz obniżyć wersję, musisz poprawnie zastąpić metodę onDowngrade zamiast tego ponownie zgłaszać błąd.

Możesz być tego świadomy, więc spróbuj zapamiętać poprzednią wersję lub spróbuj podać 6 lub większą dla parametru wersji bazy danych.