androidx.work.WorkInfo Java Examples

The following examples show how to use androidx.work.WorkInfo. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LttrsRepository.java    From lttrs-android with Apache License 2.0 6 votes vote down vote up
public ListenableFuture<LiveData<WorkInfo>> moveToTrash(final Collection<String> threadIds) {
    final SettableFuture<LiveData<WorkInfo>> future = SettableFuture.create();
    IO_EXECUTOR.execute(() -> {
        final LttrsDatabase database = requireDatabase();
        for (MailboxWithRoleAndName mailbox : database.mailboxDao().getMailboxesForThreads(threadIds)) {
            if (mailbox.role != Role.TRASH) {
                insertQueryItemOverwrite(threadIds, mailbox);
            }
        }
        for (String keyword : KeywordUtil.KEYWORD_ROLE.keySet()) {
            insertQueryItemOverwrite(threadIds, keyword);
        }
        database.overwriteDao().insertMailboxOverwrites(
                MailboxOverwriteEntity.of(threadIds, Role.INBOX, false)
        );
        database.overwriteDao().insertMailboxOverwrites(
                MailboxOverwriteEntity.of(threadIds, Role.TRASH, true)
        );
        final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MoveToTrashWorker.class)
                .setConstraints(CONNECTED_CONSTRAINT)
                .setInputData(MoveToTrashWorker.data(requireAccount().id, threadIds))
                .setInitialDelay(INITIAL_DELAY_DURATION, TimeUnit.SECONDS)
                .addTag(AbstractMuaWorker.TAG_EMAIL_MODIFICATION)
                .build();
        final WorkManager workManager = WorkManager.getInstance(application);
        workManager.enqueue(workRequest);
        future.set(workManager.getWorkInfoByIdLiveData(workRequest.getId()));
    });
    return future;
}
 
Example #2
Source File: UpdateActivity.java    From commcare-android with Apache License 2.0 6 votes vote down vote up
private void connectToUpdateWorker() {
    WorkManager.getInstance(getApplicationContext())
            .getWorkInfosForUniqueWorkLiveData(UpdateHelper.getUpdateRequestName())
            .observe(this, listOfWorkInfo -> {

                if (listOfWorkInfo == null || listOfWorkInfo.isEmpty()) {
                    return;
                }

                WorkInfo updateInfo = listOfWorkInfo.get(0);
                boolean running = updateInfo.getState() == WorkInfo.State.RUNNING;
                if (running) {
                    Data data = updateInfo.getProgress();
                    publishUpdateProgress(data.getInt(UpdateWorker.Progress_Complete, -1),
                            data.getInt(UpdateWorker.Progress_Total, -1));
                } else {
                    // Worker getting fired when not running imply completion of worker
                    ResultAndError<AppInstallStatus> lastUpdateResult = getlastStageUpdateResult();
                    if (lastUpdateResult != null) {
                        handleTaskCompletion(getlastStageUpdateResult());
                    }
                }
            });
}
 
Example #3
Source File: ThreadViewModel.java    From lttrs-android with Apache License 2.0 6 votes vote down vote up
public void waitForEdit(UUID uuid) {
    final WorkManager workManager = WorkManager.getInstance(getApplication());
    LiveData<WorkInfo> liveData = workManager.getWorkInfoByIdLiveData(uuid);
    liveData.observeForever(new Observer<WorkInfo>() {
        @Override
        public void onChanged(WorkInfo workInfo) {
            if (workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                final Data data = workInfo.getOutputData();
                final String threadId = data.getString("threadId");
                if (threadId != null && !ThreadViewModel.this.threadId.equals(threadId)) {
                    LOGGER.info("redirecting to thread {}", threadId);
                    threadViewRedirect.postValue(new Event<>(threadId));
                }
                liveData.removeObserver(this);
            } else if (workInfo.getState() == WorkInfo.State.FAILED) {
                liveData.removeObserver(this);
            }
        }
    });
}
 
Example #4
Source File: PlatformWorkManagerTest.java    From android-job with Apache License 2.0 6 votes vote down vote up
private void testConstraints(JobRequest.Builder builder) {
    int jobId = builder
            .setRequiredNetworkType(JobRequest.NetworkType.METERED)
            .setRequiresBatteryNotLow(true)
            .setRequiresCharging(true)
            .setRequiresDeviceIdle(true)
            .setRequiresStorageNotLow(true)
            .build()
            .schedule();

    String tag = JobProxyWorkManager.createTag(jobId);
    List<WorkInfo> statuses = mWorkManagerRule.getWorkStatus(tag);

    assertThat(statuses).isNotNull().hasSize(1);
    assertThat(statuses.get(0).getState()).isEqualTo(WorkInfo.State.ENQUEUED);

    mWorkManagerRule.getManager().cancelAllForTag(TAG);
    assertThat(mWorkManagerRule.getWorkStatus(tag).get(0).getState()).isEqualTo(WorkInfo.State.CANCELLED);
}
 
Example #5
Source File: PlatformWorkManagerTest.java    From android-job with Apache License 2.0 6 votes vote down vote up
@Test
@SuppressWarnings("ConstantConditions")
public void testCancel() {
    int jobId = new JobRequest.Builder(TAG)
            .setExecutionWindow(TimeUnit.HOURS.toMillis(4), TimeUnit.HOURS.toMillis(5))
            .build()
            .schedule();

    JobRequest request = mWorkManagerRule.getManager().getJobRequest(jobId);
    JobProxyWorkManager jobProxyWorkManager = new JobProxyWorkManager(ApplicationProvider.getApplicationContext());
    assertThat(jobProxyWorkManager.isPlatformJobScheduled(request)).isTrue();

    String tag = JobProxyWorkManager.createTag(jobId);
    List<WorkInfo> statuses = mWorkManagerRule.getWorkStatus(tag);

    assertThat(statuses).isNotNull().hasSize(1);
    assertThat(statuses.get(0).getState()).isEqualTo(WorkInfo.State.ENQUEUED);

    mWorkManagerRule.getManager().cancel(jobId);
    assertThat(mWorkManagerRule.getWorkStatus(tag).get(0).getState()).isEqualTo(WorkInfo.State.CANCELLED);
    assertThat(jobProxyWorkManager.isPlatformJobScheduled(request)).isFalse();
}
 
Example #6
Source File: MessagesAdapter.java    From tindroid with Apache License 2.0 6 votes vote down vote up
private boolean cancelUpload(long msgId) {
    final String uniqueID = Long.toString(msgId);

    WorkManager wm = WorkManager.getInstance(mActivity);
    WorkInfo.State state = null;
    try {
        List<WorkInfo> lwi = wm.getWorkInfosForUniqueWork(uniqueID).get();
        if (!lwi.isEmpty()) {
            WorkInfo wi = lwi.get(0);
            state = wi.getState();
        }
    } catch (ExecutionException | InterruptedException ignored) {
    }

    if (state == null || !state.isFinished()) {
        wm.cancelUniqueWork(Long.toString(msgId));
        return true;
    }
    return state == WorkInfo.State.CANCELLED;
}
 
Example #7
Source File: SyncActivity.java    From dhis2-android-capture-app with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
private void handleDataState(WorkInfo.State dataState) {
    switch (dataState) {
        case RUNNING:
            binding.eventsText.setText(getString(R.string.syncing_data));
            Bindings.setDrawableEnd(binding.eventsText, AppCompatResources.getDrawable(this, R.drawable.animator_sync));
            binding.eventsText.setAlpha(1.0f);
            break;
        case SUCCEEDED:
            binding.eventsText.setText(getString(R.string.data_ready));
            Bindings.setDrawableEnd(binding.eventsText, AppCompatResources.getDrawable(this, R.drawable.animator_done));
            /*presenter.scheduleSync(getSharedPreferences().getInt(Constants.TIME_META, Constants.TIME_DAILY),
                    getSharedPreferences().getInt(Constants.TIME_DATA, Constants.TIME_15M));*/
            presenter.syncReservedValues();
            startMain();
            break;
        default:
            break;
    }
}
 
Example #8
Source File: LttrsRepository.java    From lttrs-android with Apache License 2.0 5 votes vote down vote up
public void cancelMoveToTrash(final WorkInfo workInfo, final Collection<String> threadIds) {
    Preconditions.checkNotNull(workInfo, "Unable to cancel moveToTrash operation.");
    WorkManager.getInstance(application).cancelWorkById(workInfo.getId());
    IO_EXECUTOR.execute(() -> {
        requireDatabase().overwriteDao().revertMoveToTrashOverwrites(threadIds);
    });
}
 
Example #9
Source File: PlatformWorkManagerRule.java    From android-job with Apache License 2.0 5 votes vote down vote up
public List<WorkInfo> getWorkStatus(String tag) {
    try {
        return WorkManager.getInstance(getContext()).getWorkInfosByTag(tag).get();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
 
Example #10
Source File: JobProxyWorkManager.java    From android-job with Apache License 2.0 5 votes vote down vote up
private List<WorkInfo> getWorkStatusBlocking(String tag) {
    WorkManager workManager = getWorkManager();
    if (workManager == null) {
        return Collections.emptyList();
    }

    try {
        return workManager.getWorkInfosByTag(tag).get(5, TimeUnit.SECONDS);
    } catch (Exception e) {
        return Collections.emptyList();
    }
}
 
Example #11
Source File: JobProxyWorkManager.java    From android-job with Apache License 2.0 5 votes vote down vote up
@Override
public boolean isPlatformJobScheduled(JobRequest request) {
    List<WorkInfo> infos = getWorkStatusBlocking(createTag(request.getJobId()));
    if (infos == null || infos.isEmpty()) {
        return false;
    }

    WorkInfo.State state = infos.get(0).getState();
    return state == WorkInfo.State.ENQUEUED;
}
 
Example #12
Source File: SyncActivity.java    From dhis2-android-capture-app with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
private void handleMetaState(WorkInfo.State metadataState) {
    switch (metadataState) {
        case RUNNING:
            Bindings.setDrawableEnd(binding.metadataText, AppCompatResources.getDrawable(this, R.drawable.animator_sync));
            break;
        case SUCCEEDED:
            binding.metadataText.setText(getString(R.string.configuration_ready));
            Bindings.setDrawableEnd(binding.metadataText, AppCompatResources.getDrawable(this, R.drawable.animator_done));
            presenter.getTheme();
            break;
        default:
            break;
    }
}
 
Example #13
Source File: SyncActivity.java    From dhis2-android-capture-app with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
@Override
protected void onResume() {
    super.onResume();
    workManagerController.getWorkInfosForUniqueWorkLiveData(Constants.INITIAL_SYNC).observe(this, workInfoList -> {
        for (WorkInfo wi : workInfoList) {
            if (wi.getTags().contains(Constants.META_NOW))
                handleMetaState(wi.getState());
            else if (wi.getTags().contains(Constants.DATA_NOW))
                handleDataState(wi.getState());
        }
    });
}
 
Example #14
Source File: SyncManagerFragment.java    From dhis2-android-capture-app with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
@Override
public void onResume() {
    super.onResume();
    context.registerReceiver(networkReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
    workManagerController.getWorkInfosByTagLiveData(META_NOW).observe(this, workStatuses -> {
        if (!workStatuses.isEmpty() && workStatuses.get(0).getState() == WorkInfo.State.RUNNING) {
            binding.syncMetaLayout.message.setTextColor(ContextCompat.getColor(context, R.color.text_black_333));
            String metaText = metaSyncSettings().concat("\n").concat(context.getString(R.string.syncing_configuration));
            binding.syncMetaLayout.message.setText(metaText);
            metadataWorkRunning = true;
        } else {
            metadataWorkRunning = false;
            presenter.checkData();
        }
        checkSyncMetaButtonStatus();
    });
    workManagerController.getWorkInfosByTagLiveData(DATA_NOW).observe(this, workStatuses -> {
        if (!workStatuses.isEmpty() && workStatuses.get(0).getState() == WorkInfo.State.RUNNING) {
            String dataText = dataSyncSetting().concat("\n").concat(context.getString(R.string.syncing_data));
            binding.syncDataLayout.message.setTextColor(ContextCompat.getColor(context, R.color.text_black_333));
            binding.syncDataLayout.message.setText(dataText);
            dataWorkRunning = true;
        } else {
            dataWorkRunning = false;
            presenter.checkData();
        }
        checkSyncDataButtonStatus();
    });
    presenter.init();

    if (!getResources().getBoolean(R.bool.sms_enabled)) {
        binding.settingsSms.getRoot().setVisibility(View.GONE);
    }
}
 
Example #15
Source File: WatchFaceUtil.java    From PixelWatchFace with GNU General Public License v3.0 5 votes vote down vote up
public static <T> void observeUntilFinished(final LiveData<WorkInfo> liveData,
    final Observer<WorkInfo> observer) {
  liveData.observeForever(new Observer<WorkInfo>() {
    @Override
    public void onChanged(WorkInfo workInfo) {
      if (workInfo != null && workInfo.getState().isFinished()) {
        Log.d("observeOnce", "Removing observer, work finished.");
        liveData.removeObserver(this);
      }
      observer.onChanged(workInfo);
    }
  });
}
 
Example #16
Source File: WorkInfoUtil.java    From lttrs-android with Apache License 2.0 5 votes vote down vote up
private static Collection<WorkInfo.State> transform(List<WorkInfo> info) {
    return Collections2.transform(info, new Function<WorkInfo, WorkInfo.State>() {
        @NullableDecl
        @Override
        public WorkInfo.State apply(@NullableDecl WorkInfo input) {
            return input == null ? null : input.getState();
        }
    });
}
 
Example #17
Source File: FlutterUploaderPlugin.java    From flutter_uploader with MIT License 4 votes vote down vote up
@Override
public void onChanged(List<WorkInfo> workInfoList) {
  FlutterUploaderPlugin plugin = this.plugin.get();

  if (plugin == null) {
    return;
  }

  for (WorkInfo info : workInfoList) {
    String id = info.getId().toString();
    if (!plugin.completedTasks.containsKey(id)) {
      if (info.getState().isFinished()) {
        plugin.completedTasks.put(id, true);
        Data outputData = info.getOutputData();

        switch (info.getState()) {
          case FAILED:
            int failedStatus =
                outputData.getInt(UploadWorker.EXTRA_STATUS, UploadStatus.FAILED);
            int statusCode = outputData.getInt(UploadWorker.EXTRA_STATUS_CODE, 500);
            String code = outputData.getString(UploadWorker.EXTRA_ERROR_CODE);
            String errorMessage = outputData.getString(UploadWorker.EXTRA_ERROR_MESSAGE);
            String[] details = outputData.getStringArray(UploadWorker.EXTRA_ERROR_DETAILS);
            plugin.sendFailed(id, failedStatus, statusCode, code, errorMessage, details);
            break;
          case CANCELLED:
            plugin.sendFailed(
                id,
                UploadStatus.CANCELED,
                500,
                "flutter_upload_cancelled",
                "upload has been cancelled",
                null);
            break;
          case SUCCEEDED:
            int status = outputData.getInt(UploadWorker.EXTRA_STATUS, UploadStatus.COMPLETE);
            Map<String, String> headers = null;
            Type type = new TypeToken<Map<String, String>>() {}.getType();
            String headerJson = info.getOutputData().getString(UploadWorker.EXTRA_HEADERS);
            if (headerJson != null) {
              headers = plugin.gson.fromJson(headerJson, type);
            }

            String response = info.getOutputData().getString(UploadWorker.EXTRA_RESPONSE);
            plugin.sendCompleted(id, status, response, headers);
            break;
        }
      }
    }
  }
}
 
Example #18
Source File: WorkInfoUtil.java    From lttrs-android with Apache License 2.0 4 votes vote down vote up
public static boolean allDone(List<WorkInfo> info) {
    return Iterables.all(
            transform(info),
            s -> s != null && s != WorkInfo.State.ENQUEUED && s != WorkInfo.State.RUNNING
    );
}
 
Example #19
Source File: LttrsViewModel.java    From lttrs-android with Apache License 2.0 4 votes vote down vote up
public void cancelMoveToTrash(final WorkInfo workInfo, final Collection<String> threadIds) {
    this.threadRepository.cancelMoveToTrash(workInfo, threadIds);
}
 
Example #20
Source File: LocationGeofenceEditorActivity.java    From PhoneProfilesPlus with Apache License 2.0 4 votes vote down vote up
private void startIntentService(boolean updateName) {
    /*Intent intent = new Intent(this, FetchAddressIntentService.class);
    intent.putExtra(RECEIVER, mResultReceiver);
    intent.putExtra(LOCATION_DATA_EXTRA, mLocation);
    intent.putExtra(UPDATE_NAME_EXTRA, updateName);
    startService(intent);*/

    Data workData = new Data.Builder()
            .putDouble(LATITUDE_EXTRA, mLocation.getLatitude())
            .putDouble(LONGITUDE_EXTRA, mLocation.getLongitude())
            .putBoolean(UPDATE_NAME_EXTRA, updateName)
            .build();

    OneTimeWorkRequest fetchAddressWorker =
            new OneTimeWorkRequest.Builder(FetchAddressWorker.class)
                    .addTag(LocationGeofenceEditorActivity.FETCH_ADDRESS_WORK_TAG)
                    .setInputData(workData)
                    .build();

    try {
        if (PPApplication.getApplicationStarted(true)) {
            WorkManager workManager = PPApplication.getWorkManagerInstance();
            if (workManager != null) {
                workManager.enqueueUniqueWork(LocationGeofenceEditorActivity.FETCH_ADDRESS_WORK_TAG, ExistingWorkPolicy.KEEP, fetchAddressWorker);

                workManager.getWorkInfoByIdLiveData(fetchAddressWorker.getId())
                        .observe(this, new Observer<WorkInfo>() {
                            @Override
                            public void onChanged(@Nullable WorkInfo workInfo) {
                                //PPApplication.logE("LocationGeofenceEditorActivity.getWorkInfoByIdLiveData", "xxx");

                                if ((workInfo != null) && (workInfo.getState() == WorkInfo.State.SUCCEEDED)) {
                                    //PPApplication.logE("LocationGeofenceEditorActivity.getWorkInfoByIdLiveData", "WorkInfo.State.SUCCEEDED");

                                    Data outputData = workInfo.getOutputData();
                                    //PPApplication.logE("LocationGeofenceEditorActivity.getWorkInfoByIdLiveData", "outputData=" + outputData);

                                    int resultCode = outputData.getInt(RESULT_CODE, FAILURE_RESULT);
                                    //PPApplication.logE("LocationGeofenceEditorActivity.getWorkInfoByIdLiveData", "resultCode=" + resultCode);

                                    boolean enableAddressButton = false;
                                    if (resultCode == SUCCESS_RESULT) {
                                        //PPApplication.logE("LocationGeofenceEditorActivity.getWorkInfoByIdLiveData", "resultCode=" + resultCode);

                                        // Display the address string
                                        // or an error message sent from the intent service.
                                        String addressOutput = outputData.getString(RESULT_DATA_KEY);
                                        //PPApplication.logE("LocationGeofenceEditorActivity.getWorkInfoByIdLiveData", "addressOutput=" + addressOutput);

                                        addressText.setText(addressOutput);

                                        if (outputData.getBoolean(UPDATE_NAME_EXTRA, false))
                                            geofenceNameEditText.setText(addressOutput);

                                        updateEditedMarker(false);

                                        enableAddressButton = true;
                                    }

                                    GlobalGUIRoutines.setImageButtonEnabled(enableAddressButton, addressButton, getApplicationContext());
                                }
                            }
                        });
            }
        }
    } catch (Exception e) {
        //Log.e("LocationGeofenceEditorActivity.startIntentService", Log.getStackTraceString(e));
        PPApplication.recordException(e);
    }

}
 
Example #21
Source File: LttrsViewModel.java    From lttrs-android with Apache License 2.0 4 votes vote down vote up
public ListenableFuture<LiveData<WorkInfo>> moveToTrash(final Collection<String> threadIds) {
    return this.threadRepository.moveToTrash(threadIds);
}
 
Example #22
Source File: MainActivity.java    From service with Apache License 2.0 4 votes vote down vote up
/**
 * This will create a oneshot workerA task and schedule it to run once.
 * commented out code shows how to make it recur every 24 hours.
 */
public void oneshot() {
    //for a schedule once
    OneTimeWorkRequest runWorkA = new OneTimeWorkRequest.Builder(WorkerA.class)
        .build();

    /*
    //for recur schedule, say every 24 hours, comment out above, since duplicate variables.
    PeriodicWorkRequest.Builder workerkBuilder =
        new PeriodicWorkRequest.Builder(WorkerA.class, 24,  TimeUnit.HOURS);
    // ...if you want, you can apply constraints to the builder here...
    Constraints myConstraints = new Constraints.Builder()
        //.setRequiresDeviceIdle(true)
        .setRequiresCharging(true)
        // Many other constraints are available, see the
        // Constraints.Builder reference
        .build();

   // Create the actual work object:
    PeriodicWorkRequest runWorkA = workerkBuilder.setConstraints(myConstraints)
    .build();
   */

    //now enqueue the task so it can be run.
    WorkManager.getInstance(getApplicationContext()).enqueue(runWorkA);

    //not necessary, but this will tell us the status of the task.
    LiveData<WorkInfo> status = WorkManager.getInstance(getApplicationContext()).getWorkInfoByIdLiveData(runWorkA.getId());
    status.observe(this, new Observer<WorkInfo>() {
        @Override
        public void onChanged(@Nullable WorkInfo workStatus) {
            switch (workStatus.getState()) {
                case BLOCKED:
                    tv_oneshot.setText("Status is Blocked");
                    break;
                case CANCELLED:
                    tv_oneshot.setText("Status is canceled");
                    break;
                case ENQUEUED:
                    tv_oneshot.setText("Status is enqueued");
                    break;
                case FAILED:
                    tv_oneshot.setText("Status is failed");
                    break;
                case RUNNING:
                    tv_oneshot.setText("Status is running");
                    break;
                case SUCCEEDED:
                    tv_oneshot.setText("Status is succeeded");
                    break;
                default:
                    tv_oneshot.setText("Status is unknown");
            }

        }
    });
}
 
Example #23
Source File: MainActivity.java    From service with Apache License 2.0 2 votes vote down vote up
public void param() {
    // Create the Data object:
    final Data myData = new Data.Builder()
        // We need to pass three integers: X, Y, and Z
        .putInt(WorkerParameters.KEY_X_ARG, 42)
        // ... and build the actual Data object:
        .build();

    // ...then create and enqueue a OneTimeWorkRequest that uses those arguments
    OneTimeWorkRequest mathWork = new OneTimeWorkRequest.Builder(WorkerParameters.class)
        .setInputData(myData)
        .build();
    WorkManager.getInstance(getApplicationContext()).enqueue(mathWork);

    //now set the observer to get the result.
    WorkManager.getInstance(getApplicationContext()).getWorkInfoByIdLiveData(mathWork.getId())
        .observe(this, new Observer<WorkInfo>() {
            @Override
            public void onChanged(@Nullable WorkInfo status) {
                if (status != null && status.getState().isFinished()) {
                    int myResult = status.getOutputData().getInt(WorkerParameters.KEY_RESULT,
                        -1);
                    tv_param.setText("Result is " + myResult);
                }
            }
        });
}
 
Example #24
Source File: PixelWatchFace.java    From PixelWatchFace with GNU General Public License v3.0 1 votes vote down vote up
private void initWeatherUpdater(boolean forceUpdate) {
  String TAG = "initWeatherUpdater";
  if (!mSettings.isWeatherDisabled()) {
    if (ActivityCompat
        .checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
      Log.d(TAG, "requesting permission");
      requestPermissions();
    } else {
      Log.d(TAG, "last weather retrieved: " + mCurrentWeather.getTime());
      Log.d(TAG, "current time: " + System.currentTimeMillis());

      Constraints constraints = new Constraints.Builder()
          .setRequiredNetworkType(NetworkType.CONNECTED)
          .build();

      if (forceUpdate || mWeatherRequestedTime == 0
          || System.currentTimeMillis() - mWeatherRequestedTime >= TimeUnit.MINUTES
          .toMillis(WEATHER_UPDATE_INTERVAL)) {

        OneTimeWorkRequest locationUpdate =
            new OneTimeWorkRequest.Builder(LocationUpdateWorker.class)
                .setConstraints(constraints)
                // forced weather update is expected to happen sooner, so
                // try again in (30 seconds * attempt count). After 3 failed
                // attempts, it would wait 1.5 minutes before retrying again
                .setBackoffCriteria(BackoffPolicy.LINEAR, WEATHER_BACKOFF_DELAY_ONETIME,
                    TimeUnit.SECONDS)
                .build();

        OneTimeWorkRequest weatherUpdate =
            new OneTimeWorkRequest.Builder(WeatherUpdateWorker.class)
                .setConstraints(constraints)
                .setBackoffCriteria(BackoffPolicy.LINEAR, WEATHER_BACKOFF_DELAY_ONETIME,
                    TimeUnit.SECONDS)
                .build();

        WorkManager.getInstance(getApplicationContext())
            .beginUniqueWork(WEATHER_UPDATE_WORKER, ExistingWorkPolicy.REPLACE, locationUpdate)
            .then(weatherUpdate)
            .enqueue();
        mWeatherRequestedTime = System.currentTimeMillis();

        Observer<WorkInfo> weatherObserver = new Observer<WorkInfo>() {
          @Override
          public void onChanged(WorkInfo workInfo) {
            if (workInfo != null) {
              Log.d(TAG, "weatherObserver onChanged : " + workInfo.toString());
              if (workInfo.getState().isFinished()) {
                String currentWeatherJSON = workInfo.getOutputData()
                    .getString(KEY_WEATHER_JSON);
                Log.d(TAG, "outputWeather: " + currentWeatherJSON);
                Weather newCurrentWeather = new Gson()
                    .fromJson(currentWeatherJSON, Weather.class);

                // check if newCurrentWeather is actually valid
                if (newCurrentWeather != null
                    && newCurrentWeather.getTemperature() != NO_TEMPERATURE) {
                  // copy bitmap over so we don't have to regenerate it
                  if (newCurrentWeather.getIconID() == mCurrentWeather.getIconID()) {
                    newCurrentWeather
                        .setIconBitmap(mCurrentWeather.getIconBitmap(getApplicationContext()));
                  }
                  mCurrentWeather = newCurrentWeather;
                  invalidate(); // redraw to update the displayed weather
                }
              }
            }
          }
        };

        WatchFaceUtil.observeUntilFinished(WorkManager.getInstance(getApplicationContext())
            .getWorkInfoByIdLiveData(weatherUpdate.getId()), weatherObserver);
      }
    }
  }
}