Firebase überträgt Daten nicht richtig?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Firebase überträgt Daten nicht richtig?

    Hallo, ich habe folgendes Problem bei meiner App...erst einmal die grundlegende Funktion, die App soll für verschiedene Benutzer jeweils eine Punktzahl in einer Firebase Datenbank Speichern.
    Jetzt mein Problem es werden nicht immer alle Punktzahlen übertragen. Ich habe die App auf mehreren Handys ausprobiert, bei manchen geht es Problemlos bei manchen nicht (alle Android 9 und alle die selbe Appversion). Hat jemand eine Idee ob es an der App oder vlt auch an der Datenbank liegen kann? Oder wie ich diesen Fehler eingrenzen kann?...denn sobald der Debugger in Androidstudio aktiviert ist
    funktioniert alles. Ich wäre sehr Dankbar für jeden noch so kleinen Vorschlag

    MFG
    Marcel
  • Hallo eine Fehler Ursache könnte sein wenn du Code in verschiedenen Threads nicht immer richtig synchron ist.

    Du sagst im Debugger geht es kommt es nicht zu dem Fehler. Da es im Debugger ja langsamer geht und deine App ja an bestimmten stellen wohl anhält und dann der Thread auch fertig ist.

    Wie gesagt ist das eine Vermutung. Benutzt du überhaupt Threads, Asynctask, Timer, …. ? wenn ja könnte das eine Ursache sein.
    Ein Feedback auf Tipps ist auch schön. :P
  • Hallo,
    Erstmal danke für deine Antwort.
    Da ich noch recht neu in der Materie bin, bin ich mir recht unsicher ob das wirklich mit Thread gemeint ist...
    Wir benutzen einen "Timer" der unsere Systemzeit nimmt und dadurch berechnet wie viele Sekunden bisher vergangen sind.
    Das ist in meiner Sicht recht unabhängig vom Hochladen der Punkte.

    Java-Quellcode

    1. public void startStoppuhr() {
    2. final String[] secondString = new String[3];
    3. if (!timerisrunning) {
    4. if (checked != null) {
    5. start = System.currentTimeMillis();
    6. btnStartTime.setText("Abbrechen");
    7. timerisrunning = true;
    8. stoppuhr.schedule(new TimerTask() {
    9. @Override
    10. public void run() {
    11. final long longseconds = (System.currentTimeMillis() - start) / 1000;
    12. final int a = (int) longseconds;
    13. final int stunden = a / 3600;
    14. final int minuten = (a % 3600) / 60;
    15. final int sekunden = (a % 3600) % 60;
    16. secondString[0] = Integer.toString(sekunden);
    17. if (sekunden <= 9) {
    18. secondString[0] = "0" + sekunden;
    19. }
    20. secondString[1] = Integer.toString(minuten);
    21. if (minuten <= 9) {
    22. secondString[1] = "0" + minuten;
    23. }
    24. secondString[2] = Integer.toString(stunden);
    25. if (stunden <= 9) {
    26. secondString[2] = "0" + stunden;
    27. }
    28. runOnUiThread(new Runnable() {
    29. @Override
    30. public void run() {
    31. timeview.setText(secondString[2] + ":" + secondString[1] + ":" + secondString[0]);
    32. }
    33. });
    34. }
    35. }, 0, 1000);
    36. }
    37. } else {
    38. regattaAbbrechen();
    39. }
    40. }
    Alles anzeigen

    Das Grundprinzip von unserer App besteht darin Teilnehmer in eine Liste hinzuzufügen, den Timer zu starten, die Teilnehmer welche im Ziel ankommen sind zu stoppen (zeit wird in eine Map gespeichert), wenn alle gestoppt wurden wird die Zeit in punkte umgerechnet (funktioniert in dem wir alle zeiten in eine Liste einfügen und sortieren lassen), danach gehen wir die gesammte Liste durch und tragen es in die Datenbank ein. Hier der Code welcher es berechnet und dann hochladen soll.

    Java-Quellcode

    1. private void zeitBerechnung(int runde) {
    2. for(String e : userLastTime.keySet()) {
    3. zeitTabelle.put(e, userLastTime.get(e).get(runde-1));
    4. }
    5. final Map<String, Integer> unsortMap = new HashMap<>();
    6. for (boolean e :checked){
    7. if(e){
    8. auswahlAnzahl++;
    9. }
    10. }
    11. for(final Map.Entry e : zeitTabelle.entrySet()){
    12. if(!e.getValue().toString().equals("00:00:00")) {
    13. //mit dem yardstick berechnen
    14. mDatabase.child("users").child(e.getKey().toString()).addListenerForSingleValueEvent(new ValueEventListener() {
    15. @Override
    16. public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
    17. int yardstickDb = Integer.parseInt(dataSnapshot.child("Yardstick").getValue().toString());
    18. int zeitInSekunden;
    19. int berechneteYardstickzeit;
    20. String numbers = e.getValue().toString();
    21. String[] split = numbers.split(":");
    22. zeitInSekunden = Integer.parseInt(split[2]);
    23. zeitInSekunden += Integer.parseInt(split[1])*60;
    24. zeitInSekunden += Integer.parseInt(split[0])*60*60;
    25. berechneteYardstickzeit = (zeitInSekunden*100)/yardstickDb;
    26. berechnungsZähler++;
    27. unsortMap.put(e.getKey().toString(),berechneteYardstickzeit);//hilfe
    28. //berechnung fertig
    29. if (berechnungsZähler >= auswahlAnzahl){
    30. Map<String, Integer> sortedMap = sortByValue(unsortMap);
    31. int i = 0;
    32. for (String key : sortedMap.keySet()) {
    33. i++;
    34. if (i == 1){
    35. alleUser.put(key, 0.);
    36. }
    37. if(i == 2){
    38. alleUser.put(key, 3.);
    39. }
    40. if(i == 3){
    41. alleUser.put(key, 5.7);
    42. }
    43. if(i == 4){
    44. alleUser.put(key, 8.);
    45. }
    46. if(i == 5){
    47. alleUser.put(key, 10.);
    48. }
    49. if(i == 6){
    50. alleUser.put(key, 11.7);
    51. }
    52. if(i >= 7){
    53. alleUser.put(key, i+6.);
    54. }
    55. }
    56. //bei neue Regatta
    57. if(auswahl.equals("Neue Regatta")){
    58. for (String key : alleUser.keySet()) {
    59. mDatabase.child("regatten").child(Integer.toString(regatten+1)).child("1").child(key).setValue(alleUser.get(key));
    60. }
    61. regattaAbbrechen();
    62. }
    63. //Bei Neuer Lauf
    64. else if(auswahl.equals("Neuer Lauf")){
    65. mDatabase.child("regatten").child(Integer.toString(regatten)).addListenerForSingleValueEvent(new ValueEventListener() {
    66. @Override
    67. public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
    68. lauf = 0;
    69. Iterator<DataSnapshot> dataSnapshots = dataSnapshot.getChildren().iterator();
    70. while (dataSnapshots.hasNext()) {
    71. DataSnapshot dataSnapshotChild = dataSnapshots.next();
    72. lauf++;
    73. }
    74. for (String key : alleUser.keySet()) {
    75. try{
    76. Thread.sleep(600);
    77. }catch(InterruptedException e){}
    78. mDatabase.child("regatten").child(Integer.toString(regatten)).child(Integer.toString(lauf+1)).child(key).setValue(alleUser.get(key));
    79. }
    80. regattaAbbrechen();
    81. }
    82. @Override
    83. public void onCancelled(@NonNull DatabaseError databaseError) {
    84. }
    85. });
    86. }
    87. }
    88. }
    89. @Override
    90. public void onCancelled(@NonNull DatabaseError databaseError) {
    91. }
    92. });
    93. }
    94. }
    95. }
    Alles anzeigen
  • Das Thread.sleep() war nur versehnentlich noch drin vom austesten wie man den Fehler beheben kann. Hatte die Hoffnung das die Datenbank die Teilnehmer nur nicht schnell genug abspeichern kann.
    Wie gesagt werden die Teilnehmer alle einzelt gestoppt und in eine Map gespeichert. Dann gibt es einen finish button der mit einem Dialog abfragt ob man sich sicher ist.
    Sobald man auf ja drückt wird Zeitberechnung gestartet.
    Der Dialog wird wiederum aufgerufen durch ein OnClickListener aufgerufen.
  • Wenn ich mich nicht komplett irre ist es doch so das man mit ValueEventListener() daten aus der DB erhält also liest und nicht schreibt.

    Dann machst du auch noch in einem lister bei neuen laugf wider einen listner . Ist ja fast schon Recursion das wird auf dauer nicht gut gehn.

    Wenn ich es richtig verstehe kannst du nur etwas schreiben wenn du neue veränderte daten erhalten hast. denn du schreibst im listner. Wenn keine neuen daten ankommen der listner nicht aufgerufen wird kannst du hiermit auch nichts schreiben.
    mDatabase.child("regatten").child(Integer.toString(regatten+1)).child("1").child(key).setValue(alleUser.get(key));
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von jogimuc ()

  • Wenn es hilft könntest du dir das Projekt auf GitHub anschauen, allerdings da es mittlerweile doch recht umfassend ist, ist es wohl recht verwirrend xD.
    Der Timer ist ausschließlich dafür da die Zeit anzuzeigen, siehe oben rechts auf dem Bild. Zudem Speiern wir da die "System.currentTimeMillis()" in die variable start ab um später bei den einzelnen Teilnehmern ihre gestoppte zeit auszurechnen. Also um später einfach zu sagen wir drücken auf zeit stoppen dann wird System.currentTimeMillis() - start gemacht.
  • Den ValueEventListener() benötigen wir in der Zeitberechnung um die gestoppte Zeit mit einem Benutzerspezifischen wert zu verrechnen. Heißt damit holen wir uns den dazugehörigen wert. Verrechnen ihn. Sortieren die Zeiten. Je nachdem wer erste usw. ist gibt es verschiedene punktzahlen die dann mit

    Java-Quellcode

    1. for (String key : alleUser.keySet()) {
    2. mDatabase.child("regatten").child(Integer.toString(regatten+1)).child("1").child(key).setValue(alleUser.get(key));
    3. }
    hochgeladen werden.
    Damit das für jeden Teilnehmer gemacht wird geht er dabei die gesamte Liste durch.
  • jogimuc schrieb:

    ok schaue ich mir an heut ist es mir zu spät.

    wo welche Adresse auf github?

    Nicht abschrecken lassen. Da das meine erste App ist ist vieles in deinen Augen wohl noch recht seltsam geschrieben xD.
    Falls irgendetwas unklar ist einfach fragen.

    Ps.: Richtig fettes Dankeschön das du dir die Zeit nimmst um mir bei dem Problem zu helfen. Hab schon so viel getestet und in google findet man nichts über so einen Fehler deshalb weiß ich mir echt nicht mehr zu helfen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Kurmuro ()

  • "System.currentTimeMillis()" in die variable start ab um später bei den einzelnen Teilnehmern ihre gestoppte zeit auszurechnen. Also um später einfach zu sagen wir drücken auf zeit stoppen dann wird System.currentTimeMillis() - start gemacht.

    Findet das Local auf dem Handy statt oder in der DB. Ich würde das in der DB Machen die Start und Stopp zeit festhalten. Und die System Server zeit benutzen.
    Also wird wie oft wird denn die DB geupdatet denn nur dann wird auch wider der Leistner aufgerufen und es könne daten gesendet werden.
    Ein Feedback auf Tipps ist auch schön. :P
  • jogimuc schrieb:

    ja das habe ich schon verstanden. wird denn auch noch von wo anders estwas in die Db geschrieben.
    In dem Zusammenhang ist das das einzige wo in die Datenbank geschrieben wird.

    Es gibt noch die Funktion generell Benutzer anzulegen aber das hat absolut garnichts damit zu tun.
    In dieser Klasse werden nur diese Spezifischen werte abgerufen, verrechnet und dann in die Datenbank geschrieben.
  • Und da scheint das Problem zu liegen. Denn nur wenn daten geändert werden wird bei den anderen Teilnehmernder listner aufgerufen und sie haben die Möglichkeit etwas zu senden . sonnst nicht . wenn keiner etwas ändert steht das ganze ding.
    System.currentTimeMillis() wird Local gemacht. Was hätte es für einen Vorteil die Serverzeit zu benutzen? Die Teilnehmer stoppen kann sowieso nur eine einzige Person später heißt das Problem mit Zeitmanipulationen vom Benutzer selbst wird nicht passieren.
    ok aber der der Stopt sollte die Möglichkeit habe außerhalb des listners daten zu senden sonst wird das nicht ordentlich laufen.
    Ein Feedback auf Tipps ist auch schön. :P
  • Da steige ich gerade nicht so ganz durch. Die Zeit an sich funktioniert ja. Also an dem Screenshot siehst du ja das es bei jedem Benutzer die gestoppte Zeit dann gleich anzeigt. Heißt soweit funktioniert es ja. Zusätzlich zu dem die Zeit angezeigt wird wird es ja in eine Map gespeichert. Mithilfe dieser Map wird dann Später die Zeit berechnet.
    Da ja die Zeit immer richtig angezeigt wird kann es daran ja garnicht liegen... Oder?