2

Meine Anwendung für Studenten downloadet Markierungen in einem Hintergrunddienst und überprüft, ob es mehr Markierungen als beim letzten Mal gibt. Wenn neue Markierungen vorhanden sind, wird die Benachrichtigung verschoben und die Anzahl der Markierungen in sharedPreferences neu geschrieben. Es funktioniert, aber manchmal erstellt es mehrere Benachrichtigungen für die gleiche Marke zur gleichen Zeit.Android-Dienst setInexactAssyncTask-Problem mit SharedPreferences

Die IntentService welche löst einen Rundfunkempfänger:

public int onStartCommand(Intent intent, int flags, int startId) { 
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
    Intent i = new Intent(getApplicationContext(), CheckNewMarksReceiver.class); 
    PendingIntent alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0); 

    alarmManager.setInexactRepeating(
      AlarmManager.ELAPSED_REALTIME_WAKEUP, 
      0, 
      2500, alarmIntent); 

    return START_STICKY; 
} 

Der Rundfunkempfänger OnReceive Methode initialisiert sharedPreferences Attribut und numberOfMarksSaved und startet AsyncTask dass Downloads Daten:

DownloadDataTask task = new DownloadDataTask(); 
task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password); 

dataPreferences = context.getApplicationContext().getSharedPreferences(context.getString(R.string.SHARED_PREFERENCES), Context.MODE_PRIVATE); 
numberOfMarksSaved = dataPreferences.getInt(context.getString(R.string.PREFERENCE_NUMBER_OF_MARKS_KEY), -1); 

AsyncTasks onPostExecute Methode überprüft, ob die Anzahl der heruntergeladenen Markierungen größer als beim letzten Mal ist:

if (numberOfDownloadedMarks > numberOfMarksSaved) { 
    ... 
    notifyUserAbout(newMarks, response); // method to fire a notification 
} 

dataPreferences 
    .edit() 
    .putInt(context.getString(R.string.PREFERENCE_NUMBER_OF_MARKS_KEY), 
      numberOfDownloadedMarks) 
    .apply(); 

Wie gesagt, dies meistens funktioniert, aber manchmal die BroadcastReceiver werden zweimal in Folge sofort ausgelöst - die erste schreibt den Wert in sharedPreferences, aber der zweite merkt nicht, dass der Wert in den gemeinsamen Einstellungen geändert wurde. Wie kann ich das verhindern?

EDIT: Ich habe sogar versucht, anstatt setInexactRepeating setRepeating - nichts geändert (ich vermute, android Alarmmanager Zeitverschiebung). Hier mein Log ist:

06-11 18: 14: 27,732 ... I/So gut an: Herunterladen neue Daten

06-11 18: 14: 27,761 ... I/So gut an: neue Daten herunterladen

06-11 18: 14: 27,907 ... I/Gespeichert & neu: 89, 90

06-11 18: 14: 27,933 ... I/Mitteilung gebacken - ID: 1077819997

06-11 18: 14: 28.004 ... I/Gespeichert & neu: 89, 90

06-11 18: 14: 28,006 ... I/gebacken Benachrichtigung - ID: 1077820069

+0

Es gab eine Antwort, die den Wechsel von unexaktem Wiederholen zu Wiederholen nahelegte. Es hat nicht geholfen. – cuddlecheek

Antwort

1

Wege, wie ungenaue Wiederholung Alarme arbeiten und die langen Laufhintergrundoperationen, wahrscheinlich gibt es mehr AsyncTask-Instanzen auf die gleiche Zeit, wenn das Problem auftritt.

Aus der Dokumentation von AlarmManager:

Ihren Alarm erster Trigger wird nicht vor der gewünschten Zeit, aber es vielleicht nicht für fast ein volles Intervall nach dieser Zeit auftreten. In Zusätzlich, während die Gesamtdauer des Wiederholungsalarms wie angefordert wird, kann die Zeit zwischen zwei aufeinanderfolgenden Abfeuerungen des Alarms variieren.

Für solch niedrigen Intervalle würde ich vorschlagen, setRepeating() zu verwenden, anstatt setInexactRepeating()

und

eine Instanz Ihrer AsyncTask in Ihrem Service halten.

Dann könnten Sie so etwas tun:

if(task.getStatus == AsyncTask.Status.FINISHED) { 
    task = new DownloadDataTask(); 
    task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password); 
} 

mehrere Instanzen Ihrer AsyncTask zur gleichen Zeit zu verhindern, ausgeführt wird.

+0

Ich benutze dies in einem Handler mit postDelayed im Dienst und es funktioniert wie ein Zauber. Vielen Dank. – cuddlecheek