Android Datenbank - Was passiert wenn ein User ein Update überspringt?

  • Antworten:13
  • Bentwortet
yumperz
  • Forum-Beiträge: 17

28.12.2013, 23:44:14 via Website

Hallo,

nachdem ich gestern bereits ein Post gestartet habe, in dem es um Datenbank arbeiten ging, stellte sich mir heute eine neue frage:

Was passiert, wenn ich als Entwickler eine neue Version meiner App rausbringe. und der Benutzer dieses Update nicht tätigt. Er wartet also auf ein weiteres Update und nimmt erst dieses er springt sogesehen von version 1.1 direkt auf version 1.3 und lässt 1.2 aus.
Nehmen wir als Beispiel ein Quiz: Ich habe ein Quiz erstellt indem es 200 Fragen gibt. nun möchte ich mit einem Update 500 neue fragen hinzufügen.
Der Benutzer macht das update nicht!
Ich bringe ein weiteres Update und nocheinmal 300 neue fragen.
Der Benutzer macht erst dieses Update und überspringt somit das vorherige mit den 500 neuen fragen.
Das würde doch jetzt bedeuten, das der benutzer nur die 300 neuen fragen bekommt und die 500 vorherigen einfach wegfallen bzw nicht vorhanden sind auf seinem Gerät.

Muss ich also einen Versionsverlauf in meine Updatemethode schreiben und dann sagen in welcher datenbankversion welche einträge hinzugekommen sind?
als Beispiel:
1oldversion += 1;
2while (oldversion < newversion) {
3getOlderVersionData(oldversion);
4oldversion++;
5}

Antworten
Carsten M.
  • Forum-Beiträge: 33.204

28.12.2013, 23:48:02 via App

yumperz

Das würde doch jetzt bedeuten, das der benutzer nur die 300 neuen fragen bekommt und die 500 vorherigen einfach wegfallen bzw nicht vorhanden sind auf seinem Gerät.
So ist es.

Deine angedachte Lösung ist also nicht praxistauglich. Da musst Du Dir was neues ausdenken...

Herzliche Grüße

Carsten

Ich komm' mir langsam vor wie jemand, der ich bin // #cäthe

Antworten
yumperz
  • Forum-Beiträge: 17

28.12.2013, 23:59:22 via App

Hey Danke für die schnelle Antwort :)

also sollte man Benutzer Daten immer in separaten Tabellen speichern und nicht die Tabellen benutzen, die öfter erweitert werden?
Das Quiz war nur ein schnelles Beispiel es handelt sich eigentlich um ein Spiel in denen es NPCs gibt, also eine Tabelle mit "Personen" Daten und eine Tabelle "User".
der User beinhaltet eine Person (also die ID einer Person in der Tabelle person)
dieses hindert mich jetzt daran, die Tabelle Personen zu löschen und einfach bei einem update neu anzulegen (Verlust der User Daten)

Gruß
Kevin

Antworten
Daniel K.
  • Forum-Beiträge: 474

29.12.2013, 01:15:27 via App

Ich kenne mich da absolut nicht aus, finde es aber schon interessant.
Ist es nicht so, so denke ich zumindest das es so wäre, das bei Updates die komplette App aktualisiert wird, und nicht nur erweitert?

Beispiel Facebook.
Ungefähr 17 MB groß. Bei Updates muss ich aber jedes mal die vollen 17 MB laden. Und es ist ja nicht so, dass kleine Performance Updates 17 MB groß sind.
Bei größeren Anwendungen, wie Zb Spielen, verhält es sich meiner Beobachtung nach genauso.

Demnach müsste jemand der direkt von 1.1 auf 1.3 springt, wie in deinem gut nachvollziehbaren Beispiel, doch auch den vollen Umfang erhalten.

— geändert am 29.12.2013, 01:16:57

Samsung Galaxy Note 3, Stock Firmware

Antworten
Gelöschter Account
  • Forum-Beiträge: 8.735

29.12.2013, 01:51:30 via App

Es geht nicht um den Code der App sondern um User-Daten, die lokal auf dem Android Device vorliegen.

Ich habe keine Lust mehr auf Bastelei und widme mich lieber wieder dem Real Life. Die Idee gärte schon länger. Tschüß!


Antworten
Gelöschter Account
  • Forum-Beiträge: 8.735

29.12.2013, 02:09:55 via Website

yumperz
ein Spiel in denen es NPCs gibt, also eine Tabelle mit "Personen" Daten und eine Tabelle "User".
der User beinhaltet eine Person (also die ID einer Person in der Tabelle person)
dieses hindert mich jetzt daran, die Tabelle Personen zu löschen und einfach bei einem update neu anzulegen (Verlust der User Daten)

Ich würde eine leere User-Tabelle anlegen, die aber nur dann erstellt wird, wenn sie noch nicht auf dem Device vorhanden ist. Ansonsten bleibt die vorhandene unangetastet.

Eine weitere Tabelle enthält alle Fragen. Du musst darauf achten, dass sich in dieser Tabelle die Primärschlüssel für alte Fragen bei Updates nie ändern sondern nur neue hinzukommen. Dann kannst Du diese Tabelle immer komplett neu erstellen, beziehungsweise leeren und neu füllen.

Zusätzlich richtest Du eine Matching-Tabelle ein, die ebenfalls nur dann neu erstellt wird, wenn sie nicht existiert. Existiert sie, lässt Du sie unangetastet.
Hier sind ausschließlich die Relationen zwischen den Primärschlüsseln der User-Tabelle und den Primärschlüsseln der Fragen-Tabelle enthalten.

Ändert sich die Struktur der User- und/oder Matching-Tabelle, musst Du den Datenbestand exportieren, umwandeln und nach dem Schreiben der neuen Tabellen importieren. Das kann sogar grundsätzlich einen Update-Weg darstellen.

— geändert am 29.12.2013, 02:22:52


Ich habe keine Lust mehr auf Bastelei und widme mich lieber wieder dem Real Life. Die Idee gärte schon länger. Tschüß!


Antworten
NoAh!
  • Forum-Beiträge: 1.445

29.12.2013, 10:47:34 via App

und wie wäre es, wenn man die fragen alle auf einem Server lagern würde, und nach dem update einfach geprüft wird Welche Fragen fehlen und diese dann inapp gedownloaded werden?

— geändert am 29.12.2013, 10:48:39

Grüße NoAh!

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

29.12.2013, 11:02:57 via Website

springt sogesehen von version 1.1 direkt auf version 1.3 und lässt 1.2 aus

Geh das doch mal logisch an: was brauchst du um dieses Problem zu lösen?
1. Die Version der Datenbank - sollte in dieser gespeichert sein
2. Die aktuelle Version - deine App weiß das, weil du es weißt
3. Wissen darüber, was in welcher Version geändert wurde - deine App kann das leicht wissen, wenn du es entsprechend implementierst.

Daraus ergibt sich dann als Skizze:

int old = getVersionFromDB(), orig = old;

switch (old) {
case 100:
// Änderungen von 1.00 auf 1.10
if (update100to110() == false) break;
old = 110;
/*fall thru*/
case 110:
// Änderungen von 1.10 auf 1.20
if (update110to120() == false) break;
old = 120;
/*fall thru*/
...
case 130:
// im Beispiel die aktuelle Version
}
if (old != orig) saveVersionToDB(old);

yumperz

Antworten
yumperz
  • Forum-Beiträge: 17

29.12.2013, 11:59:31 via App

Das würde also für mich bedeuten das User-daten strikt von den Tabellen in denen Daten hinzu kommen getrennt sein sollten um die Tabelle dann löschen zu können und hinterher neu zu erstellen mit veränderten Daten.
das Prinzip mit der extra Tabelle die nur die Relation von User und person enthält würde also nicht funktionieren da die Person des Users beim update gelöscht werden würde und nur die Person der NPCs neu erstellt werden würden.

und wenn ich die Skizze richtig verstanden habe dann meinst du genau das was ich anfangs schrieb (für jedes update eine eigene Methode hinzufügen und die Methoden nacheinander abarbeiten wenn die Version kleiner ist als die neueste version).

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

29.12.2013, 13:29:15 via Website

Das würde also für mich bedeuten das User-daten strikt von den Tabellen in denen Daten hinzu kommen getrennt sein sollten um die Tabelle dann löschen zu können und hinterher neu zu erstellen mit veränderten Daten.

Das bezieht sich jetzt nicht auf meine Skizze, oder?
Falls doch: nein, mit dem Konzept brauchst du nichts zu trennen und auch nichts zu löschen/neu aufzubauen.

für jedes update eine eigene Methode hinzufügen und die Methoden nacheinander abarbeiten wenn die Version kleiner ist als die neueste version

Ausgehend von der vorliegenden DB-Version bis hin zur aktuellen Version, ja.
In meinen Projekten sind die App-Version und die DB-Version unabhängig voneinander, und die DB-Version wird für jedes SQL-Statement erhöht, die Skizze (mit den App-Versionsnummern) sollte nur beim Verständnis helfen.

Antworten
SvenDD
  • Forum-Beiträge: 272

29.12.2013, 15:20:19 via Website

Es eigentlich Recht einfach:
Du hast ja deine DatabaseHandler-Klasse die von SQLiteHelper erbt.

Dort hast du bestimmt einen static int definiert:
1private static final int DATABASE_VERSION = 2;
//2 ist z.B. die Version 2 der Datenbank.

In der Klasse selber brauchst du nur die zwei Methoden implementieren:

//Konstruktor
1public DatabaseHandler(Context context) {
2super(context, DATABASE_NAME, null, DATABASE_VERSION);
3cont = context;
4}

//Datenbank erstellen
1@Override
2 public void onCreate(SQLiteDatabase db) {
3 // Tabellen implementieren
4 db.beginTransaction();
5 try {
6 db.execSQL(CREATE_TABLE_ENTRY);
7 db.setTransactionSuccessful();
8 } finally {
9 db.endTransaction();
10 }
11 }

//Updatemethoden der Dankenbank
1@Override
2 public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
3 // Tabellen upgraden für neue Funktionen
4 switch (oldV) {
5 case 1:
6 db.execSQL(UPDATE_TABLE_ENTRY_V2);
7 default:
8 break;
9 }
10 }

Je mehr Updates du machst, desto mehr cases hast du am Ende.

yumperz

Antworten
yumperz
  • Forum-Beiträge: 17

30.12.2013, 11:35:00 via Website

Danke für eure schnellen Hilfen! =)

hab es mir so ähnlich gedacht, nur kann man anstelle eines switch case doch auch eine forschleife nehmen und dann mit Method.invoke die gegebene Methode aufrufen, die dann dementsprechend den SQL-String zurück gibt?
Nur mal für mich zum verständnis:

1for (oldDbVersion++; oldDbVersion <= newDbVersion ;oldDbVersion++) {
2 String str = "UpdateVersion" + oldDbVersion;
3 DatabaseHandler invokeDb = this;
4 Method m = invokeDb.getClass().getMethod(str);
5 Object objectSql = m.invoke(invokeDb);
6 String sql = (String)objectSql;
7 db.execSQL(sql);
8 db.execSQL(
9}

Antworten
yumperz
  • Forum-Beiträge: 17

30.12.2013, 11:36:03 via Website

NoAh!
und wie wäre es, wenn man die fragen alle auf einem Server lagern würde, und nach dem update einfach geprüft wird Welche Fragen fehlen und diese dann inapp gedownloaded werden?

Wäre möglich, aber für das was ich vor habe eher sinnbefreiend leider =(
Wie gesagt es geht nicht um ein Quiz, nur war es so am einfachsten zu erklären ;-)

Antworten
impjor
  • Forum-Beiträge: 1.793

30.12.2013, 11:49:39 via App

Reflection ist nie so schön und sollte nur im Notfall benutzt werden.
Wenn du in den einzelnen Funktionen aber nur Text für ein execSql zurück geben wollstest (und nicht mehrere komplexere Aufgaben) sollte es funktionieren.
LG

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

yumperz

Antworten