webentwicklung-frage-antwort-db.com.de

Läuft ein Dienst, auch wenn das Telefon schläft?

Ich habe einen Dienst in meiner Anwendung, der alle 10 Minuten ausgeführt werden soll. Grundsätzlich wird auf unseren Servern überprüft, ob alles ordnungsgemäß funktioniert, und der Benutzer wird über Probleme informiert. Ich habe diese Anwendung für den internen Gebrauch in unserem Unternehmen erstellt.

Mein Kollege nutzte die Anwendung über das lange Wochenende und stellte fest, dass keine Überprüfungen durchgeführt wurden, als das Gerät in den Ruhezustand ging. Ich hatte den Eindruck, dass der Service im Hintergrund weiterlaufen sollte, bis ich in meinem Code explizit stopService() aufrufe.

Letztendlich ist es mein Ziel, den Dienst so lange laufen zu lassen, bis der Benutzer die Aus-Taste in der Anwendung drückt oder den Prozess abbricht.

Ich habe von etwas namens WakeLock gehört, das verhindern soll, dass sich der Bildschirm ausschaltet, was ich nicht will. Ich habe dann von einem anderen Ding namens partielles WakeLock gehört, das die CPU auch dann am Laufen hält, wenn das Gerät schläft. Letzteres klingt näher an das, was ich brauche.

Wie erwerbe ich dieses WakeLock und wann soll ich es veröffentlichen und gibt es andere Möglichkeiten, dies zu umgehen?

51
PaulG

Hinweis: Dieser Beitrag wurde aktualisiert und enthält nun die JobScheduler-API der Android Lollipop-Version. Die folgenden Angaben sind noch möglich, können jedoch als veraltet betrachtet werden, wenn Sie eine Ausrichtung vornehmen Android Lollipop und darüber hinaus. In der zweiten Hälfte finden Sie die JobScheduler - Alternative.

Eine Möglichkeit, wiederkehrende Aufgaben auszuführen, ist folgende:

  • Erstelle eine Klasse AlarmReceiver

    public class AlarmReceiver extends BroadcastReceiver 
    {
        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Intent myService = new Intent(context, YourService.class);
            context.startService(myService);
        }
    }
    

    mit YourService als Service ;-)

Wenn Sie für Ihre Aufgabe eine Aktivierungssperre benötigen, ist es ratsam, von WakefulBroadcastReceiver zu verlängern. Vergessen Sie in diesem Fall nicht, die Berechtigung WAKE_LOCK In Ihr Manifest aufzunehmen!

  • Erstellen Sie eine ausstehende Absicht

Führen Sie den folgenden Code in Ihrer Aktivität aus, um die wiederholte Abfrage zu starten:

Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
//updateTime.setWhatever(0);    //set time to start first occurence of alarm 
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); //you can modify the interval of course

Dieser Code setzt ein alarm und ein canceable pendingIntent. Das alarmManager veranlasst den Job, das recurringAlarm jeden Tag zu wiederholen (drittes Argument), aber ungenau damit die CPU ungefähr nach dem Intervall aufwacht, aber nicht genau (Dadurch kann das Betriebssystem die optimale Zeit auswählen, wodurch die Batterie entladen wird.) Das erste Mal, wenn der Alarm (und damit der Dienst) gestartet wird, ist die Zeit, die Sie als updateTime festlegen.

  • last but not least: hier erfahren Sie, wie Sie den wiederkehrenden Alarm ausschalten

    Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
    //myAlarm.putExtra("project_id",project_id); //put the SAME extras
    PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarms.cancel(recurringAlarm);
    

Dieser Code erstellt eine Kopie Ihres (wahrscheinlich) vorhandenen Alarms und weist den alarmManager an, alle Alarme dieser Art abzubrechen.

  • natürlich gibt es auch in Manifest etwas zu tun:

schließen Sie diese zwei Linien ein

  < receiver Android:name=".AlarmReceiver"></receiver>
  < service Android:name=".YourService"></service>

innerhalb des < application> - Tags. Ohne diese Funktion akzeptiert das System den Start eines wiederkehrenden Alarms eines Dienstes nicht.


Ab dem Release Android Lollipop gibt es eine neue Möglichkeit, diese Aufgabe auf elegante Weise zu lösen. Dies macht es auch einfacher, eine Aktion nur dann auszuführen, wenn bestimmte Kriterien wie der Netzwerkstatus erfüllt sind.

// wrap your stuff in a componentName
ComponentName mServiceComponent = new ComponentName(context, MyJobService.class);
// set up conditions for the job
JobInfo task = JobInfo.Builder(mJobId, mServiceComponent)
   .setPeriodic(mIntervalMillis)
   .setRequiresCharging(true) // default is "false"
   .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) // Parameter may be "ANY", "NONE" (=default) or "UNMETERED"
   .build();
// inform the system of the job
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(task);

Sie können auch eine Frist mit setOverrideDeadline(maxExecutionDelayMillis) angeben.

Um eine solche Aufgabe loszuwerden, rufen Sie einfach jobScheduler.cancel(mJobId); oder jobScheduler.cancelAll(); auf.

61
stefan

Ich hätte empfohlen, wenn das Erstellen dieser Anwendung von Anfang an eine serverseitige Komponente (ja, auch Überwachung erforderlich!) Und das Senden von Push-Benachrichtigungen erfordert, ist das Abrufen niemals eine zuverlässige Lösung.

5
Lee Hambley

Aus Android Dokumentation im Doze-Modus passiert Folgendes: ( https://developer.Android.com/training/monitoring-device-state/doze-standby ):

The system ignores wake locks.

The system does not allow JobScheduler to run.

Android ignoriert AlarmManager ebenfalls, es sei denn, sie befinden sich in setAndAllowWhileIdle() or setExactAndAllowWhileIdle().

Network access is suspended.

Daher besteht die einzige Möglichkeit darin, FCM mit hoher Priorität oder AlarmManager mit setAndAllowWhileIdle () oder setExactAndAllowWhileIdle () zu verwenden.

3
Saba