JobScheduler: Steuerung der Verzögerung von der Erfüllung von Einschränkungen bis zur Ausführung des Jobs

Lesezeit: 7 Minuten

Benutzeravatar von drmrbrewer
drmrbrewer

Ich verwende JobScheduler, um Jobs zu planen. Hauptsächlich verwende ich es für .setRequiredNetworkType() -Methode, mit der Sie angeben können, dass der Auftrag nur dann geplant werden soll, wenn eine Netzwerkverbindung (oder genauer gesagt eine nicht gemessene Verbindung) hergestellt wird.

Ich verwende den folgenden ziemlich einfachen Code, um meine Jobs zu planen:

PersistableBundle extras = new PersistableBundle();
extras.putInt("anExtraInt", someInt);
int networkConstraint = useUnmetered ? JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;

ComponentName componentName = new ComponentName(context, MyJobService.class);
JobInfo jobInfo = new JobInfo.Builder(jobId, componentName)
        .setRequiredNetworkType(networkConstraint)
        .setExtras(extras)
        .build();

JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);

Es gibt also nur eine Einschränkung für die Planung: eine Netzwerkverbindung (die „beliebig“ oder „nicht gemessen“ sein kann).

Kurzfassung der Frage

Wie lege ich eine maximale Verzögerung fest, bis alle Einschränkungen erfüllt sind und der Job tatsächlich ausgeführt wird, z. B. „Führen Sie den Job innerhalb von 2 Sekunden nach der Herstellung einer Netzwerkverbindung aus“?

Längere Version (mit Geschwafel)

Das Problem

Ich stelle fest, dass auf einigen Geräten ein Auftrag für einen Zeitraum geplant ist, in dem die Netzwerkbeschränkung besteht schon zufriedenwird der Job sofort ausgeführt (oder schnell genug, um vom Benutzer als solcher wahrgenommen zu werden).

Aber auf anderen Geräten kommt es, selbst wenn bereits eine geeignete Netzwerkverbindung vorhanden ist (so dass der Job sofort ausgeführt werden kann), zu einer erheblichen Verzögerung, bevor er tatsächlich ausgeführt wird. Erfolgt dies also als Reaktion auf eine Benutzeraktion, entsteht der Eindruck, dass nichts passiert ist und die App kaputt ist.

Nun, mir ist durchaus bewusst, dass dies wahrscheinlich die Absicht ist JobScheduler… dass es Sache des Systems ist, den Job so zu planen, dass er am besten zu anderen Anforderungen passt, und dass es keine Garantie dafür gibt, dass der Job sofort ausgeführt wird, wenn alle Einschränkungen erfüllt sind.

Aber es wäre schön, wenn man es haben könnte manche Kontrolle darüber, sofern erforderlich. Für Aufgaben, die nach einem Zeitplan und ohne Eingreifen des Benutzers ausgeführt werden, ist es also in Ordnung und gut, dem System die vollständige Kontrolle über die genaue Zeitplanung zu geben.

Aber wenn der Job eine Reaktion auf eine Benutzeraktion ist, möchte ich, dass der Job ohne Verzögerung ausgeführt wird … vorausgesetzt, dass die Netzwerkverbindung vorhanden ist. (Wenn keine Verbindung besteht, kann eine Meldung angezeigt werden, dass die Aktion ausgeführt wird, wenn eine Netzwerkverbindung wiederhergestellt wird, und die JobScheduler kümmert sich dann darum, dass der Job ausgeführt wird, wenn das Netzwerk wiederhergestellt ist.)

setOverrideDeadline() ist keine Lösung?

Ich kann sehen, dass JobInfo.Builder hat ein setOverrideDeadline() Methode, die fast das ist, was ich will. Aber das gibt die maximale Verzögerung an ab dem Zeitpunkt, an dem der Job geplant ist (dh den Job in 10 Sekunden ausführen, auch wenn nicht alle Einschränkungen erfüllt sind) und nicht ab dem Zeitpunkt, an dem alle Auflagen erfüllt sind (dh den Job innerhalb von 10 Sekunden ausführen, nachdem alle Einschränkungen erfüllt sind).

EDIT: Und es scheint einen lästigen Fehler zu geben, der dazu führen kann, dass der Job bei der Verwendung zweimal ausgeführt wird setOverrideDeadline(): siehe hier und hier.

Was ist mit Firebase JobDispatcher?

Ich sehe das Firebase JobDispatcher hat ein Trigger.NOW Abzug („bedeutet, dass der Job ausgeführt werden soll, sobald seine Laufzeitbeschränkungen erfüllt sind“). Vielleicht ist das der richtige Weg, wenn JobSchedulerunterstützt dies nicht nativ? Ich bin von Firebase JobDispatcher abgeschreckt worden, weil es so aussieht, als würde es einen Vorschlaghammer benutzen, um eine Nuss zu knacken … und es scheint, dass es bei Firebase nur um Cloud-Messaging usw. geht, was sehr weit von der lokalen Aufgabenplanung entfernt ist (was eine sein sollte). rein lokales Anliegen). Und es scheint Google Play-Dienste zu erfordern, was wiederum für die lokale Aufgabenplanung völlig unnötig erscheint. Darüber hinaus ist eine sofortige Auslösung mit Firebase möglich, und Firebase nutzt es einfach JobScheduler für Android L+, dann muss es sicher möglich sein, dies direkt damit zu tun JobScheduler ohne auf Firebase angewiesen zu sein?

EDIT: Ich habe das jetzt ausprobiert und sogar Trigger.NOW garantiert keine sofortige Antwort … Tatsächlich stelle ich fest, dass es auf meinem Gerät eine Verzögerung von fast genau 30 Sekunden gibt, was seltsam ist.

Gelingt das nicht…

Die einzige Möglichkeit, die ich derzeit sehe, um eine sofortige Ausführung sicherzustellen (sofern die Einschränkungen erfüllt sind), besteht darin, Folgendes zu tun: nicht verwenden JobScheduler.

Oder führen Sie die anfängliche Einschränkungsprüfung manuell durch und führen Sie den Job mit einem aus setOverrideDeadline() von 0, wenn alle Einschränkungen erfüllt sind, andernfalls wird es ohne ausgeführt setOverrideDeadline().

Es wäre weitaus vorzuziehen, einfach nur die Möglichkeit zu haben, das Timing zu kontrollieren JobScheduler selbst, ein bisschen wie man es mit dem kann setWindow() Methode von AlarmManager.

  • @OP, könnten Sie Ihren Beitrag bitte in kleinere Unterkategorien einteilen, in denen dargelegt wird, was Sie in Bezug auf das Problem, das Sie beheben möchten, sagen möchten?

    – JoxTraex

    8. September 2016 um 8:00 Uhr


  • @JoxTraex Das hatte ich bereits versucht (Kurzversion vs. Langversion), aber ich habe jetzt mehr Unterstruktur hinzugefügt. Niemand muss über die Kurzversion hinaus lesen, aber die Langversion bietet mehr Hintergrundinformationen.

    – drmrbrewer

    8. September 2016 um 8:42

  • Wie Sie angedeutet haben, vermute ich, dass dieser Mangel an API beabsichtigt ist. Sie können natürlich gerne danach fragen, ob es sich um eine Funktionserweiterung handelt, allerdings würde eine solche Erweiterung (vermutlich) bestenfalls erst bei Android O auftauchen, was bedeutet, dass es 2022 dauern wird, bis eine solche Funktion alltäglich wird. „Vielleicht führen Sie die anfängliche Einschränkungsprüfung manuell durch und führen den Job mit einem setOverrideDeadline() von 0 aus, wenn alle Einschränkungen erfüllt sind, andernfalls führen Sie ihn ohne setOverrideDeadline() aus“ – oder erledigen Sie einfach die Arbeit, wenn die Einschränkungen erfüllt sind, und überspringen Sie die Arbeit. Es macht keinen Sinn, es zu verwenden JobScheduler für die sofortige Arbeit.

    – CommonsWare

    10. September 2016 um 20:17 Uhr

  • Also @CommonsWare, wenn ich eine habe JobService Gibt es eine Möglichkeit, dies direkt und nicht über a auszuführen? JobSchedulerwenn ich möchte, dass es einfach läuft Jetzt? Ich hasse es, Code zu duplizieren und einen separaten zu erstellen Service denn das scheint (selbst mit gemeinsam genutzten Funktionen) unelegant zu sein … viel ordentlicher, nur um damit anzufangen JobService direkt?

    – drmrbrewer

    10. September 2016 um 21:08 Uhr

  • „Wenn ich möchte, dass es jetzt einfach läuft?“ – AFAIK, Sie können anrufen startService() allein JobService. Refaktorieren Sie die tatsächlich zu erledigende Arbeit in einer separaten Klasse (für Ihren Hintergrundthread), die daraus erstellt und verwendet werden kann onStartJob() oder von startService(). Es sieht nicht so aus, als ob Sie ein erstellen können JobParameters dich selbst, also kannst du es nicht haben startService() Forderung onStartJob()es sei denn, Sie haben bestanden null für die JobParameters.

    – CommonsWare

    10. September 2016 um 21:12 Uhr

Ein Job-Scheduler dient zum Planen von Jobs: periodisches Auslösen, mit Verzögerung oder mit Einschränkungen für andere Jobs. Wenn Sie einen Auftrag sofort auslösen möchten, muss er nicht geplant werden. Starten Sie ihn einfach.

ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = cm.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnectedOrConnecting()) {

        // If there is connectivity, Launch the job directly here

    } else {

        PersistableBundle extras = new PersistableBundle();
        extras.putInt("anExtraInt", someInt);
        int networkConstraint = useUnmetered ?       
        JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;

        ComponentName componentName = new ComponentName(context,MyJobService.class);
        JobInfo jobInfo = new JobInfo.Builder(jobId, componentName)
                .setRequiredNetworkType(networkConstraint)
                .setExtras(extras)
                .build();

        JobScheduler jobScheduler = (JobScheduler)      context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        jobScheduler.schedule(jobInfo);
    }

1452550cookie-checkJobScheduler: Steuerung der Verzögerung von der Erfüllung von Einschränkungen bis zur Ausführung des Jobs

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy