Как создать работу с WorkManager, когда устройство подключено? - PullRequest
1 голос
/ 25 марта 2019

Я хочу создать задание, которое будет запускаться, когда устройство подключено, точно так же, как широковещательный приемник для ACTION_POWER_CONNECTED.

Вот рабочий класс:

public class ChargerWorker extends Worker {

/* Constants */
    private static final String TAG = "ChargerWorker";
    private static final long TRIGGER_AGE = TimeUnit.MINUTES.toMillis(30);       // At least 30 min old.

    @NonNull
    @Override
    public Result doWork() {
        Log.e(TAG, "Power connection worker of Indoor/Outdoor lib.");
        IndoorOutdoorLogger.v(TAG, "Power connection worker of Indoor/Outdoor lib.");
        Context context = getApplicationContext();

        if (Conditions.isBatteryChargingOnAC(context)) {
            IndoorOutdoorLogger.d(context, TAG, "Power plugged and connected to AC.");
            Log.e(TAG, "Power plugged and connected to AC.");

            if (WiFiConnection.isWifiConnected(context) && WiFiConnection.isCurrentNetworkIndoorRecognized(context)) {
                // In this case an "upgrade" to the confidence level is possible.
                // Only run when the last known detection is old enough.
                DetectionResult latestResult = DetectionResult.loadFromCache(context);
                if (!latestResult.isTimestampValid(TRIGGER_AGE)) {
                    IndoorOutdoorLogger.d(context, TAG, "AC power while connected to a recognized WiFi network, and last detection is old enough, starting detection.");
                    IndoorOutdoorClient client = new IndoorOutdoorClient(context, null);
                    client.startShortDetection(Trigger.POWER);
                }
            }
        }
        return Result.SUCCESS;
    } }

Вот как я инициализирую работу в моем методе onCreate ():

Constraints constraints = new Constraints.Builder().setRequiresCharging(true).build();
        OneTimeWorkRequest simpleReuquest = new OneTimeWorkRequest.Builder(ChargerWorker.class)
                .setConstraints(constraints)
                .build();
        WorkManager.getInstance().enqueue(simpleReuquest);

При первом подключении устройства к адаптеру все работает как надо. Однако, когда я отсоединяю устройство и пытаюсь повторить, я больше никогда не получаю доступ к функции doWork. Вместо этого я вижу следующее сообщение в logcat:

E/WorkerWrapper: Status for 031e39f1-bc10-4a35-9341-11453fc0ca21 is SUCCEEDED; not doing any work.

Это потому, что я использую OneTimeWorkRequest? Если да, как я могу запланировать его запуск при каждом подключении устройства к источнику питания?

1 Ответ

1 голос
/ 25 марта 2019

Это равно , поскольку вы используете OnTimeWorkRequest, из его названия вы можете сделать вывод, что запрос действителен только один раз.После запуска он не будет вызываться снова, если только вы не запустите его снова.Проблема в том, что WorkManager не поддерживает другие запросы или ограничения, которые соответствуют вашим потребностям.Посмотрите на этот вопрос .

Если вы действительно хотите использовать этот паттерн WorkManger и Requests, я могу дать вам идею, основанную на том факте, что людикак правило, каждый раз заряжайте телефон дольше нескольких минут.

Вы можете использовать 2 типа WorkRequests вместе взятых:

  • OneTimeWorkRequest, что является фактическимлогика вашего алгоритма.Установите ограничения, чтобы быть только во время зарядки.После запуска этот работник помещает в очередь PeriodicWorkRequest без каких-либо ограничений и «Минимальный интервал повторения, который можно определить, составляет 15 минут»

  • PeriodicWorkRequest, которыйэто будет срабатывать каждые 15 минут и периодически проверять, заряжается ли телефон.Когда работник в первый раз обнаруживает, что устройство отключено от сети, он ставит в очередь OneTimeWorkRequest сверху и отменяет сам себя.

Таким образом, вы не обнаружите быстрых изменений состояния питания устройства,но это лучший вариант в Android Oreo (и выше), поскольку приложения , предназначенные для уровня API 26 или выше, больше не могут регистрировать приемники широковещания для неявных трансляций в своем манифесте

Чтобы проверить,устройство подключено или нет:

Вы даже можете определить, какая это зарядка, используйте этот код:

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);

// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                 status == BatteryManager.BATTERY_STATUS_FULL;

// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;

взято прямо из руководства разработчика Android

Чтобы отменить WorkRequest:

Сначала создайте его с помощью tag:

OneTimeWorkRequest.Builder(MyWorker.class)
            .setConstraints(myConstraints)
            .addTag(tag)
            .build();

, а затем выполните WorkManager.getInstance().cancelAllWorkByTag(tag)

Другой вариантпоставить в очередь уникальную работу:

WorkManager.getInstance().enqueueUniquePeriodicWork(
            uniqueWorkName, ExistingPeriodicWorkPolicy.REPLACE, periodicWork);

и затем отменить ее с WorkManager.getInstance().cancelUniqueWork(workName)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...