From 4f7f49e1e714ce41320fff569272a1423198b2f3 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 14 Mar 2023 21:03:45 +0100 Subject: [PATCH] Move feed download to worker (#6375) Feed downloads are now independent from episode downloads. This makes it easier to use WorkManager for refreshing. Also, it will make it easier to add different refresh intervals in the future. --- .../test/antennapod/ui/FeedSettingsTest.java | 58 +----- .../test/antennapod/ui/PreferencesTest.java | 28 --- .../antennapod/activity/MainActivity.java | 48 +++-- .../activity/OnlineFeedViewActivity.java | 7 +- .../activity/OpmlImportActivity.java | 4 +- .../dialog/FeedRefreshIntervalDialog.java | 117 ------------ .../fragment/CompletedDownloadsFragment.java | 4 +- .../fragment/EpisodesListFragment.java | 15 +- .../fragment/FeedItemlistFragment.java | 20 +-- .../fragment/FeedSettingsFragment.java | 5 +- .../antennapod/fragment/QueueFragment.java | 21 ++- .../fragment/SubscriptionFragment.java | 62 ++++--- .../NetworkPreferencesFragment.java | 65 +------ .../menuhandler/FeedMenuHandler.java | 13 +- .../preferences/PreferenceUpgrader.java | 7 +- .../antennapod/receiver/SPAReceiver.java | 11 +- .../antennapod/ui/home/HomeFragment.java | 20 +-- .../de/danoeh/antennapod/view/TimePicker.java | 31 ---- .../main/res/layout/feed_refresh_dialog.xml | 40 ----- app/src/main/res/layout/scrollable_dialog.xml | 37 ---- app/src/main/res/xml/preferences_network.xml | 7 +- core/build.gradle | 1 + .../core/backup/OpmlBackupAgent.java | 11 +- .../core/receiver/FeedUpdateReceiver.java | 4 +- .../core/service/FeedUpdateWorker.java | 166 +++++++++++++++-- .../service/download/DownloadService.java | 139 ++------------- .../DownloadServiceInterfaceImpl.java | 6 +- .../download/handler/FeedSyncTask.java | 14 +- .../antennapod/core/storage/DBTasks.java | 101 ++--------- .../antennapod/core/storage/DBWriter.java | 10 +- .../antennapod/core/sync/SyncService.java | 20 ++- .../core/util/download/AutoUpdateManager.java | 167 ------------------ .../core/util/download/FeedUpdateManager.java | 112 ++++++++++++ core/src/main/res/values/arrays.xml | 22 +++ core/src/main/res/values/ids.xml | 1 + .../event/FeedUpdateRunningEvent.java | 9 + .../serviceinterface/DownloadRequest.java | 6 +- .../storage/database/PodDBAdapter.java | 7 + .../storage/preferences/UserPreferences.java | 72 +------- ui/i18n/src/main/res/values/strings.xml | 17 +- 40 files changed, 533 insertions(+), 972 deletions(-) delete mode 100644 app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/view/TimePicker.java delete mode 100644 app/src/main/res/layout/feed_refresh_dialog.xml delete mode 100644 app/src/main/res/layout/scrollable_dialog.xml delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/download/FeedUpdateManager.java create mode 100644 event/src/main/java/de/danoeh/antennapod/event/FeedUpdateRunningEvent.java diff --git a/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java index f3cd99b2c..861c62f1b 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/FeedSettingsTest.java @@ -2,13 +2,11 @@ package de.test.antennapod.ui; import android.content.Intent; import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedPreferences; import de.test.antennapod.EspressoTestUtils; import org.junit.After; import org.junit.Before; @@ -18,8 +16,6 @@ import org.junit.runner.RunWith; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.pressBack; -import static androidx.test.espresso.action.ViewActions.typeText; import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isRoot; @@ -28,10 +24,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static de.test.antennapod.EspressoTestUtils.clickPreference; import static de.test.antennapod.EspressoTestUtils.waitForView; import static org.hamcrest.Matchers.allOf; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.IOException; @RunWith(AndroidJUnit4.class) public class FeedSettingsTest { @@ -84,52 +76,4 @@ public class FeedSettingsTest { clickPreference(R.string.feed_volume_reduction); onView(withText(R.string.cancel_label)).perform(click()); } - - /** - * Test that modifying a feed's authentication settings results in proper behavior. - * Expect: - * - Feed is refreshed automatically - * - Database has updated username and password - */ - @Test - public void testAuthenticationSettingsUpdate() throws IOException { - onView(isRoot()).perform(waitForView(allOf(isDescendantOfA(withId(R.id.appBar)), - withText(feed.getTitle()), isDisplayed()), 1000)); - - String updatedTitle = "modified episode title"; - String username = "username"; - String password = "password"; - - // update feed hosted on server - feed.getItems().get(0).setTitle(updatedTitle); - uiTestUtils.hostFeed(feed); - - // interact with UI to update authentication settings - updateAuthenticationSettings(username, password); - - // expect feed to have refreshed and be showing new episode title - onView(isRoot()).perform(waitForView(withText(updatedTitle), 5000)); - - // expect database to be updated with correct username and password - Feed updatedFeed = DBReader.getFeed(feed.getId()); - assertNotNull(updatedFeed); - - FeedPreferences updatedFeedPreferences = updatedFeed.getPreferences(); - assertNotNull(updatedFeedPreferences); - - assertEquals("database updated with username", username, updatedFeedPreferences.getUsername()); - assertEquals("database updated with password", password, updatedFeedPreferences.getPassword()); - } - - private void updateAuthenticationSettings(String username, String password) { - onView(withId(R.id.butShowSettings)).perform(click()); - - clickPreference(R.string.authentication_label); - onView(withId(R.id.usernameEditText)).perform(typeText(username)); - onView(withId(R.id.passwordEditText)).perform(typeText(password)); - onView(withText(R.string.confirm_label)).perform(click()); - - onView(isRoot()).perform(pressBack()); - } - } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index b790bc005..1b8100392 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -5,7 +5,6 @@ import android.content.SharedPreferences; import android.content.res.Resources; import androidx.annotation.StringRes; import androidx.preference.PreferenceManager; -import androidx.test.espresso.matcher.RootMatchers; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; import de.danoeh.antennapod.R; @@ -25,9 +24,7 @@ import org.junit.Rule; import org.junit.Test; import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard; @@ -46,7 +43,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static de.test.antennapod.EspressoTestUtils.clickPreference; import static de.test.antennapod.EspressoTestUtils.waitForView; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.hamcrest.Matchers.anything; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertTrue; @@ -226,30 +222,6 @@ public class PreferencesTest { .until(() -> pauseForFocusLoss == UserPreferences.shouldPauseForFocusLoss()); } - @Test - public void testDisableUpdateInterval() { - clickPreference(R.string.network_pref); - clickPreference(R.string.feed_refresh_title); - onView(withText(R.string.feed_refresh_never)).perform(click()); - onView(withId(R.id.disableRadioButton)).perform(click()); - onView(withText(R.string.confirm_label)).perform(click()); - Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getUpdateInterval() == 0); - } - - @Test - public void testSetUpdateInterval() { - clickPreference(R.string.network_pref); - clickPreference(R.string.feed_refresh_title); - onView(withId(R.id.intervalRadioButton)).perform(click()); - onView(withId(R.id.spinner)).perform(click()); - int position = 1; // an arbitrary position - onData(anything()).inRoot(RootMatchers.isPlatformPopup()).atPosition(position).perform(click()); - onView(withText(R.string.confirm_label)).perform(click()); - Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getUpdateInterval() == TimeUnit.HOURS.toMillis(2)); - } - @Test public void testSetSequentialDownload() { clickPreference(R.string.network_pref); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index 9c771f161..7851e5b9a 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -22,36 +22,31 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; -import com.google.android.material.appbar.MaterialToolbar; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentContainerView; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.recyclerview.widget.RecyclerView; +import androidx.work.WorkInfo; +import androidx.work.WorkManager; import com.bumptech.glide.Glide; +import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.snackbar.Snackbar; - -import de.danoeh.antennapod.core.preferences.ThemeSwitcher; -import de.danoeh.antennapod.fragment.AllEpisodesFragment; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.Validate; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - import de.danoeh.antennapod.R; -import de.danoeh.antennapod.storage.preferences.UserPreferences; +import de.danoeh.antennapod.core.preferences.ThemeSwitcher; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.dialog.RatingDialog; +import de.danoeh.antennapod.event.FeedUpdateRunningEvent; import de.danoeh.antennapod.event.MessageEvent; import de.danoeh.antennapod.fragment.AddFeedFragment; +import de.danoeh.antennapod.fragment.AllEpisodesFragment; import de.danoeh.antennapod.fragment.AudioPlayerFragment; import de.danoeh.antennapod.fragment.CompletedDownloadsFragment; -import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.fragment.FeedItemlistFragment; +import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.fragment.NavDrawerFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; @@ -60,10 +55,16 @@ import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.fragment.TransitionEffect; import de.danoeh.antennapod.playback.cast.CastEnabledActivity; import de.danoeh.antennapod.preferences.PreferenceUpgrader; +import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter; import de.danoeh.antennapod.ui.common.ThemeUtils; import de.danoeh.antennapod.ui.home.HomeFragment; import de.danoeh.antennapod.view.LockableBottomSheetBehavior; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.Validate; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; /** * The activity that is shown when the user launches the app. @@ -157,6 +158,21 @@ public class MainActivity extends CastEnabledActivity { sheetBehavior = (LockableBottomSheetBehavior) BottomSheetBehavior.from(bottomSheet); sheetBehavior.setHideable(false); sheetBehavior.setBottomSheetCallback(bottomSheetCallback); + + FeedUpdateManager.restartUpdateAlarm(this, false); + WorkManager.getInstance(this) + .getWorkInfosByTagLiveData(FeedUpdateManager.WORK_TAG_FEED_UPDATE) + .observe(this, workInfos -> { + boolean isRefreshingFeeds = false; + for (WorkInfo workInfo : workInfos) { + if (workInfo.getState() == WorkInfo.State.RUNNING) { + isRefreshingFeeds = true; + } else if (workInfo.getState() == WorkInfo.State.ENQUEUED) { + isRefreshingFeeds = true; + } + } + EventBus.getDefault().postSticky(new FeedUpdateRunningEvent(isRefreshingFeeds)); + }); } @Override @@ -241,9 +257,7 @@ public class MainActivity extends CastEnabledActivity { private void checkFirstLaunch() { SharedPreferences prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE); if (prefs.getBoolean(PREF_IS_FIRST_LAUNCH, true)) { - // for backward compatibility, we only change defaults for fresh installs - UserPreferences.setUpdateInterval(12); - AutoUpdateManager.restartUpdateAlarm(this); + FeedUpdateManager.restartUpdateAlarm(this, true); SharedPreferences.Editor edit = prefs.edit(); edit.putBoolean(PREF_IS_FIRST_LAUNCH, false); @@ -553,7 +567,7 @@ public class MainActivity extends CastEnabledActivity { drawerLayout.open(); } if (intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false)) { - AutoUpdateManager.runImmediate(this); + FeedUpdateManager.runOnceOrAsk(this); } // to avoid handling the intent twice when the configuration changes setIntent(new Intent(MainActivity.this, MainActivity.class)); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index 50aabbd01..f5f3d28f6 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -36,7 +36,7 @@ import de.danoeh.antennapod.core.preferences.ThemeSwitcher; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; import de.danoeh.antennapod.core.feed.FeedUrlNotFoundException; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; +import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface; import de.danoeh.antennapod.core.util.DownloadErrorLabel; import de.danoeh.antennapod.event.FeedListUpdateEvent; @@ -455,10 +455,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { if (feedInFeedlist()) { openFeed(); } else { - Feed f = new Feed(selectedDownloadUrl, null, feed.getTitle()); - DownloadServiceInterface.get().download(this, false, DownloadRequestCreator.create(f) - .withAuthentication(username, password) - .build()); + DBTasks.updateFeed(this, feed, false); didPressSubscribe = true; handleUpdatedFeedStatus(); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java index 64a6b6632..10a41057c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java @@ -29,7 +29,7 @@ import de.danoeh.antennapod.core.export.opml.OpmlReader; import de.danoeh.antennapod.core.preferences.ThemeSwitcher; import de.danoeh.antennapod.core.storage.DBTasks; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.databinding.OpmlSelectionBinding; import de.danoeh.antennapod.model.feed.Feed; import io.reactivex.Completable; @@ -101,7 +101,7 @@ public class OpmlImportActivity extends AppCompatActivity { feed.setItems(Collections.emptyList()); DBTasks.updateFeed(this, feed, false); } - DownloadServiceInterface.get().refreshAllFeeds(this, true); + FeedUpdateManager.runOnce(this); }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java deleted file mode 100644 index 3d92fd979..000000000 --- a/app/src/main/java/de/danoeh/antennapod/dialog/FeedRefreshIntervalDialog.java +++ /dev/null @@ -1,117 +0,0 @@ -package de.danoeh.antennapod.dialog; - -import android.content.Context; -import android.content.res.Resources; -import android.os.Build; -import android.text.format.DateFormat; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ArrayAdapter; -import androidx.appcompat.app.AlertDialog; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; -import de.danoeh.antennapod.databinding.FeedRefreshDialogBinding; -import de.danoeh.antennapod.databinding.ScrollableDialogBinding; -import de.danoeh.antennapod.storage.preferences.UserPreferences; -import java.util.concurrent.TimeUnit; -import org.apache.commons.lang3.ArrayUtils; - -public class FeedRefreshIntervalDialog { - private static final int[] INTERVAL_VALUES_HOURS = {1, 2, 4, 8, 12, 24, 72}; - private final Context context; - private FeedRefreshDialogBinding viewBinding; - - public FeedRefreshIntervalDialog(Context context) { - this.context = context; - } - - public void show() { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context); - builder.setTitle(R.string.feed_refresh_title); - builder.setMessage(R.string.feed_refresh_sum); - ScrollableDialogBinding scrollableDialogBinding = ScrollableDialogBinding.inflate(LayoutInflater.from(context)); - builder.setView(scrollableDialogBinding.getRoot()); - viewBinding = FeedRefreshDialogBinding.inflate(LayoutInflater.from(context)); - scrollableDialogBinding.content.addView(viewBinding.getRoot()); - - ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(context, - android.R.layout.simple_spinner_item, buildSpinnerEntries()); - spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - viewBinding.spinner.setAdapter(spinnerArrayAdapter); - viewBinding.timePicker.setIs24HourView(DateFormat.is24HourFormat(context)); - viewBinding.spinner.setSelection(ArrayUtils.indexOf(INTERVAL_VALUES_HOURS, 24)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - viewBinding.timePicker.setHour(8); - viewBinding.timePicker.setMinute(0); - } else { - viewBinding.timePicker.setCurrentHour(8); - viewBinding.timePicker.setCurrentMinute(0); - } - - long currInterval = UserPreferences.getUpdateInterval(); - int[] updateTime = UserPreferences.getUpdateTimeOfDay(); - if (currInterval > 0) { - viewBinding.spinner.setSelection(ArrayUtils.indexOf(INTERVAL_VALUES_HOURS, - (int) TimeUnit.MILLISECONDS.toHours(currInterval))); - viewBinding.intervalRadioButton.setChecked(true); - } else if (updateTime.length == 2 && updateTime[0] >= 0) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - viewBinding.timePicker.setHour(updateTime[0]); - viewBinding.timePicker.setMinute(updateTime[1]); - } else { - viewBinding.timePicker.setCurrentHour(updateTime[0]); - viewBinding.timePicker.setCurrentMinute(updateTime[1]); - } - viewBinding.timeRadioButton.setChecked(true); - } else { - viewBinding.disableRadioButton.setChecked(true); - } - updateVisibility(); - - viewBinding.radioGroup.setOnCheckedChangeListener((radioGroup, i) -> updateVisibility()); - - AlertDialog dialog = builder.show(); - - scrollableDialogBinding.positiveButton.setText(R.string.confirm_label); - scrollableDialogBinding.positiveButton.setOnClickListener(v -> { - dialog.dismiss(); - if (viewBinding.intervalRadioButton.isChecked()) { - UserPreferences.setUpdateInterval(INTERVAL_VALUES_HOURS[viewBinding.spinner.getSelectedItemPosition()]); - AutoUpdateManager.restartUpdateAlarm(context); - } else if (viewBinding.timeRadioButton.isChecked()) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - UserPreferences.setUpdateTimeOfDay(viewBinding.timePicker.getHour(), - viewBinding.timePicker.getMinute()); - } else { - UserPreferences.setUpdateTimeOfDay(viewBinding.timePicker.getCurrentHour(), - viewBinding.timePicker.getCurrentMinute()); - } - AutoUpdateManager.restartUpdateAlarm(context); - } else if (viewBinding.disableRadioButton.isChecked()) { - UserPreferences.disableAutoUpdate(); - AutoUpdateManager.disableAutoUpdate(context); - } else { - throw new IllegalStateException("Unexpected error."); - } - }); - - scrollableDialogBinding.negativeButton.setText(R.string.cancel_label); - scrollableDialogBinding.negativeButton.setOnClickListener((v) -> dialog.dismiss()); - } - - private String[] buildSpinnerEntries() { - final Resources res = context.getResources(); - String[] entries = new String[INTERVAL_VALUES_HOURS.length]; - for (int i = 0; i < INTERVAL_VALUES_HOURS.length; i++) { - int hours = INTERVAL_VALUES_HOURS[i]; - entries[i] = res.getQuantityString(R.plurals.feed_refresh_every_x_hours, hours, hours); - } - return entries; - } - - private void updateVisibility() { - viewBinding.spinner.setVisibility(viewBinding.intervalRadioButton.isChecked() ? View.VISIBLE : View.GONE); - viewBinding.timePicker.setVisibility(viewBinding.timeRadioButton.isChecked() ? View.VISIBLE : View.GONE); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index dbc453301..737975389 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -25,7 +25,7 @@ import de.danoeh.antennapod.core.event.DownloadLogEvent; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.FeedItemUtil; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; @@ -193,7 +193,7 @@ public class CompletedDownloadsFragment extends Fragment @Override public boolean onMenuItemClick(MenuItem item) { if (item.getItemId() == R.id.refresh_item) { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); return true; } else if (item.getItemId() == R.id.action_download_logs) { new DownloadLogFragment().show(getChildFragmentManager(), null); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java index 5ba323372..18bec12ca 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -30,11 +30,11 @@ import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloaderUpdate; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.util.FeedItemUtil; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; +import de.danoeh.antennapod.event.FeedUpdateRunningEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; @@ -123,7 +123,7 @@ public abstract class EpisodesListFragment extends Fragment } final int itemId = item.getItemId(); if (itemId == R.id.refresh_item) { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); return true; } else if (itemId == R.id.action_search) { ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance()); @@ -184,7 +184,7 @@ public abstract class EpisodesListFragment extends Fragment SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh); swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance)); swipeRefreshLayout.setOnRefreshListener(() -> { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false), getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms)); }); @@ -455,9 +455,12 @@ public abstract class EpisodesListFragment extends Fragment protected abstract String getPrefName(); protected void updateToolbar() { + } + + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(FeedUpdateRunningEvent event) { if (toolbar.getMenu().findItem(R.id.refresh_item) != null) { - MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, - DownloadService.isRunning && DownloadService.isDownloadingFeeds()); + MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, event.isFeedUpdateRunning); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java index 0b264b5a3..ecc60c411 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java @@ -33,11 +33,11 @@ import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloaderUpdate; import de.danoeh.antennapod.core.feed.FeedEvent; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.FeedItemPermutors; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil; import de.danoeh.antennapod.databinding.FeedItemListFragmentBinding; import de.danoeh.antennapod.databinding.MultiSelectSpeedDialBinding; @@ -48,6 +48,7 @@ import de.danoeh.antennapod.dialog.RenameItemDialog; import de.danoeh.antennapod.event.FavoritesEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; +import de.danoeh.antennapod.event.FeedUpdateRunningEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.QueueEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; @@ -164,7 +165,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem nextPageLoader = new MoreContentListFooterUtil(viewBinding.moreContent.moreContentListFooter); nextPageLoader.setClickListener(() -> { if (feed != null) { - DBTasks.loadNextPageOfFeed(getActivity(), feed, false); + FeedUpdateManager.runOnce(getContext(), feed, true); } }); viewBinding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -241,8 +242,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem } viewBinding.toolbar.getMenu().findItem(R.id.visit_website_item).setVisible(feed.getLink() != null); - MenuItemUtils.updateRefreshMenuItem(viewBinding.toolbar.getMenu(), R.id.refresh_item, - DownloadService.isRunning && DownloadService.isDownloadingFile(feed.getDownload_url())); FeedMenuHandler.onPrepareOptionsMenu(viewBinding.toolbar.getMenu(), feed); } @@ -384,7 +383,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem private void updateUi() { loadItems(); - updateSyncProgressBarVisibility(); } @Subscribe(threadMode = ThreadMode.MAIN) @@ -404,12 +402,14 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem } } - private void updateSyncProgressBarVisibility() { - updateToolbar(); - if (!DownloadService.isDownloadingFeeds()) { + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(FeedUpdateRunningEvent event) { + nextPageLoader.setLoadingState(event.isFeedUpdateRunning); + if (!event.isFeedUpdateRunning) { nextPageLoader.getRoot().setVisibility(View.GONE); } - nextPageLoader.setLoadingState(DownloadService.isDownloadingFeeds()); + MenuItemUtils.updateRefreshMenuItem(viewBinding.toolbar.getMenu(), + R.id.refresh_item, event.isFeedUpdateRunning); } private void refreshHeaderView() { @@ -534,14 +534,12 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem adapter.setDummyViews(0); adapter.updateItems(feed.getItems()); updateToolbar(); - updateSyncProgressBarVisibility(); }, error -> { feed = null; refreshHeaderView(); adapter.setDummyViews(0); adapter.updateItems(Collections.emptyList()); updateToolbar(); - updateSyncProgressBarVisibility(); Log.e(TAG, Log.getStackTraceString(error)); }); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java index b4195ba01..ae9e003d5 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java @@ -16,7 +16,7 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.SwitchPreferenceCompat; import androidx.recyclerview.widget.RecyclerView; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.storage.DBTasks; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.event.settings.SkipIntroEndingChangedEvent; import de.danoeh.antennapod.event.settings.SpeedPresetChangedEvent; import de.danoeh.antennapod.event.settings.VolumeAdaptionChangedEvent; @@ -270,8 +270,7 @@ public class FeedSettingsFragment extends Fragment { } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } - - DBTasks.forceRefreshFeed(requireContext(), feed, true); + FeedUpdateManager.runOnce(getContext(), feed); }, "RefreshAfterCredentialChange").start(); } }.show(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java index bb22c5652..6681df4c1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -18,13 +18,13 @@ import android.widget.CheckBox; import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.android.material.appbar.MaterialToolbar; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import com.google.android.material.appbar.MaterialToolbar; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.snackbar.Snackbar; import com.leinardi.android.speeddial.SpeedDialView; import de.danoeh.antennapod.R; @@ -36,14 +36,13 @@ import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloaderUpdate; import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; -import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.FeedItemUtil; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.event.FeedItemEvent; +import de.danoeh.antennapod.event.FeedUpdateRunningEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.QueueEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; @@ -54,6 +53,7 @@ import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedItemFilter; import de.danoeh.antennapod.model.feed.SortOrder; +import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; import de.danoeh.antennapod.view.LiftOnScrollListener; @@ -263,8 +263,11 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte toolbar.getMenu().findItem(R.id.queue_lock).setVisible(!keepSorted); toolbar.getMenu().findItem(R.id.sort_random).setVisible(!keepSorted); toolbar.getMenu().findItem(R.id.keep_sorted).setChecked(keepSorted); - MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), - R.id.refresh_item, DownloadService.isRunning && DownloadService.isDownloadingFeeds()); + } + + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(FeedUpdateRunningEvent event) { + MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, event.isFeedUpdateRunning); } @Override @@ -274,7 +277,7 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte toggleQueueLock(); return true; } else if (itemId == R.id.refresh_item) { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); return true; } else if (itemId == R.id.clear_queue) { // make sure the user really wants to clear the queue @@ -457,7 +460,7 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh); swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance)); swipeRefreshLayout.setOnRefreshListener(() -> { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false), getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms)); }); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index cc13f4ce3..a0698229a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -13,20 +13,40 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; - import androidx.annotation.NonNull; -import com.google.android.material.appbar.MaterialToolbar; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - +import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.joanzapata.iconify.Iconify; import com.leinardi.android.speeddial.SpeedDialView; - +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.adapter.SubscriptionsRecyclerAdapter; +import de.danoeh.antennapod.core.event.DownloadEvent; +import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.NavDrawerData; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; +import de.danoeh.antennapod.dialog.FeedSortDialog; +import de.danoeh.antennapod.dialog.RenameItemDialog; +import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog; +import de.danoeh.antennapod.event.FeedListUpdateEvent; +import de.danoeh.antennapod.event.FeedUpdateRunningEvent; +import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; +import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler; +import de.danoeh.antennapod.menuhandler.FeedMenuHandler; +import de.danoeh.antennapod.model.feed.Feed; +import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.ui.statistics.StatisticsFragment; +import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.LiftOnScrollListener; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -35,30 +55,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.adapter.SubscriptionsRecyclerAdapter; -import de.danoeh.antennapod.core.event.DownloadEvent; -import de.danoeh.antennapod.event.FeedListUpdateEvent; -import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; -import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; -import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadService; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.NavDrawerData; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; -import de.danoeh.antennapod.dialog.FeedSortDialog; -import de.danoeh.antennapod.dialog.RenameItemDialog; -import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog; -import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler; -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.view.EmptyViewHandler; -import de.danoeh.antennapod.menuhandler.FeedMenuHandler; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - /** * Fragment for displaying feed subscriptions */ @@ -173,7 +169,7 @@ public class SubscriptionFragment extends Fragment SwipeRefreshLayout swipeRefreshLayout = root.findViewById(R.id.swipeRefresh); swipeRefreshLayout.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance)); swipeRefreshLayout.setOnRefreshListener(() -> { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); new Handler(Looper.getMainLooper()).postDelayed(() -> swipeRefreshLayout.setRefreshing(false), getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms)); }); @@ -209,16 +205,18 @@ public class SubscriptionFragment extends Fragment private void refreshToolbarState() { int columns = prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()); toolbar.getMenu().findItem(COLUMN_CHECKBOX_IDS[columns - MIN_NUM_COLUMNS]).setChecked(true); + } - MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, - DownloadService.isRunning && DownloadService.isDownloadingFeeds()); + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(FeedUpdateRunningEvent event) { + MenuItemUtils.updateRefreshMenuItem(toolbar.getMenu(), R.id.refresh_item, event.isFeedUpdateRunning); } @Override public boolean onMenuItemClick(MenuItem item) { final int itemId = item.getItemId(); if (itemId == R.id.refresh_item) { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); return true; } else if (itemId == R.id.subscriptions_filter) { SubscriptionsFilterDialog.showDialog(requireContext()); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java index 50de1e3c4..94c85abfe 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/NetworkPreferencesFragment.java @@ -1,21 +1,15 @@ package de.danoeh.antennapod.fragment.preferences; -import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; -import android.text.format.DateFormat; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; -import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.dialog.FeedRefreshIntervalDialog; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.dialog.ProxyDialog; - -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.concurrent.TimeUnit; +import de.danoeh.antennapod.storage.preferences.UserPreferences; public class NetworkPreferencesFragment extends PreferenceFragmentCompat @@ -45,7 +39,6 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat @Override public void onResume() { super.onResume(); - setUpdateIntervalText(); setParallelDownloadsText(UserPreferences.getParallelDownloads()); } @@ -54,21 +47,12 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_autodownload); return true; }); - findPreference(UserPreferences.PREF_UPDATE_INTERVAL) - .setOnPreferenceClickListener(preference -> { - new FeedRefreshIntervalDialog(getContext()).show(); - return true; - }); - - findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS) - .setOnPreferenceChangeListener( - (preference, o) -> { - if (o instanceof Integer) { - setParallelDownloadsText((Integer) o); - } - return true; - } - ); + findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS).setOnPreferenceChangeListener((preference, o) -> { + if (o instanceof Integer) { + setParallelDownloadsText((Integer) o); + } + return true; + }); // validate and set correct value: number of downloads between 1 and 50 (inclusive) findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> { ProxyDialog dialog = new ProxyDialog(getActivity()); @@ -77,35 +61,6 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat }); } - /** - * Used to init and handle changes to view - */ - private void setUpdateIntervalText() { - Context context = getActivity().getApplicationContext(); - String val; - long interval = UserPreferences.getUpdateInterval(); - if (interval > 0) { - int hours = (int) TimeUnit.MILLISECONDS.toHours(interval); - val = context.getResources().getQuantityString( - R.plurals.feed_refresh_every_x_hours, hours, hours); - } else { - int[] timeOfDay = UserPreferences.getUpdateTimeOfDay(); - if (timeOfDay.length == 2) { - Calendar cal = new GregorianCalendar(); - cal.set(Calendar.HOUR_OF_DAY, timeOfDay[0]); - cal.set(Calendar.MINUTE, timeOfDay[1]); - String timeOfDayStr = DateFormat.getTimeFormat(context).format(cal.getTime()); - val = String.format(context.getString(R.string.feed_refresh_interval_at), - timeOfDayStr); - } else { - val = context.getString(R.string.feed_refresh_never); - } - } - String summary = context.getString(R.string.feed_refresh_sum) + "\n" - + String.format(context.getString(R.string.pref_current_value), val); - findPreference(UserPreferences.PREF_UPDATE_INTERVAL).setSummary(summary); - } - private void setParallelDownloadsText(int downloads) { final Resources res = getActivity().getResources(); String s = res.getString(R.string.parallel_downloads, downloads); @@ -115,9 +70,7 @@ public class NetworkPreferencesFragment extends PreferenceFragmentCompat @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (UserPreferences.PREF_UPDATE_INTERVAL.equals(key)) { - setUpdateIntervalText(); + FeedUpdateManager.restartUpdateAlarm(getContext(), true); } } } - - diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java index 7aee499da..e9b0c0b19 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java @@ -10,6 +10,7 @@ import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.ShareUtils; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.dialog.IntraFeedSortDialog; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.SortOrder; @@ -26,6 +27,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import java.util.Collections; import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; /** @@ -64,7 +66,16 @@ public class FeedMenuHandler { if (itemId == R.id.refresh_item) { DBTasks.forceRefreshFeed(context, selectedFeed, true); } else if (itemId == R.id.refresh_complete_item) { - DBTasks.forceRefreshCompleteFeed(context, selectedFeed); + new Thread(() -> { + selectedFeed.setNextPageLink(selectedFeed.getDownload_url()); + selectedFeed.setPageNr(0); + try { + DBWriter.resetPagedFeedPage(selectedFeed).get(); + FeedUpdateManager.runOnce(context, selectedFeed); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + }).start(); } else if (itemId == R.id.sort_items) { showSortDialog(context, selectedFeed); } else if (itemId == R.id.visit_website_item) { diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java index 875ed347e..80e7fdb1e 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java @@ -13,7 +13,7 @@ import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.error.CrashReportWriter; import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.storage.preferences.UserPreferences.EnqueueLocation; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.swipeactions.SwipeAction; import de.danoeh.antennapod.fragment.swipeactions.SwipeActions; @@ -31,7 +31,7 @@ public class PreferenceUpgrader { int newVersion = BuildConfig.VERSION_CODE; if (oldVersion != newVersion) { - AutoUpdateManager.restartUpdateAlarm(context); + FeedUpdateManager.restartUpdateAlarm(context, true); CrashReportWriter.getFile().delete(); upgrade(oldVersion, context); @@ -138,6 +138,9 @@ public class PreferenceUpgrader { .apply(); } UserPreferences.setAllowMobileSync(true); + if (prefs.getString(UserPreferences.PREF_UPDATE_INTERVAL, ":").contains(":")) { // Unset or "time of day" + prefs.edit().putString(UserPreferences.PREF_UPDATE_INTERVAL, "12").apply(); + } } } } diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java index c566a1fd2..788359a4e 100644 --- a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java +++ b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java @@ -8,11 +8,12 @@ import android.util.Log; import android.widget.Toast; import java.util.Arrays; +import java.util.Collections; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.ClientConfigurator; -import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; +import de.danoeh.antennapod.core.storage.DBTasks; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.model.feed.Feed; /** @@ -43,9 +44,11 @@ public class SPAReceiver extends BroadcastReceiver{ Log.d(TAG, "Received feeds list: " + Arrays.toString(feedUrls)); ClientConfigurator.initialize(context); for (String url : feedUrls) { - Feed f = new Feed(url, null); - DownloadServiceInterface.get().download(context, false, DownloadRequestCreator.create(f).build()); + Feed feed = new Feed(url, null, "Unknown podcast"); + feed.setItems(Collections.emptyList()); + DBTasks.updateFeed(context, feed, false); } Toast.makeText(context, R.string.sp_apps_importing_feeds_msg, Toast.LENGTH_LONG).show(); + FeedUpdateManager.runOnce(context); } } diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java b/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java index da3fd7b05..778b57c8c 100644 --- a/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/ui/home/HomeFragment.java @@ -17,13 +17,12 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentContainerView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.util.download.AutoUpdateManager; +import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.databinding.HomeFragmentBinding; import de.danoeh.antennapod.event.FeedListUpdateEvent; +import de.danoeh.antennapod.event.FeedUpdateRunningEvent; import de.danoeh.antennapod.fragment.SearchFragment; import de.danoeh.antennapod.ui.home.sections.DownloadsSection; import de.danoeh.antennapod.ui.home.sections.EpisodesSurpriseSection; @@ -69,13 +68,12 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis } viewBinding.homeScrollView.setOnScrollChangeListener(new LiftOnScrollListener(viewBinding.appbar)); ((MainActivity) requireActivity()).setupToolbarToggle(viewBinding.toolbar, displayUpArrow); - refreshToolbarState(); populateSectionList(); updateWelcomeScreenVisibility(); viewBinding.swipeRefresh.setDistanceToTriggerSync(getResources().getInteger(R.integer.swipe_refresh_distance)); viewBinding.swipeRefresh.setOnRefreshListener(() -> { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); new Handler(Looper.getMainLooper()).postDelayed(() -> viewBinding.swipeRefresh.setRefreshing(false), getResources().getInteger(R.integer.swipe_to_refresh_duration_in_ms)); }); @@ -126,14 +124,10 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenSectionsString, ","))); } - private void refreshToolbarState() { - MenuItemUtils.updateRefreshMenuItem(viewBinding.toolbar.getMenu(), - R.id.refresh_item, DownloadService.isRunning && DownloadService.isDownloadingFeeds()); - } - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - refreshToolbarState(); + public void onEventMainThread(FeedUpdateRunningEvent event) { + MenuItemUtils.updateRefreshMenuItem(viewBinding.toolbar.getMenu(), + R.id.refresh_item, event.isFeedUpdateRunning); } @Override @@ -142,7 +136,7 @@ public class HomeFragment extends Fragment implements Toolbar.OnMenuItemClickLis HomeSectionsSettingsDialog.open(getContext(), (dialogInterface, i) -> populateSectionList()); return true; } else if (item.getItemId() == R.id.refresh_item) { - AutoUpdateManager.runImmediate(requireContext()); + FeedUpdateManager.runOnceOrAsk(requireContext()); return true; } else if (item.getItemId() == R.id.action_search) { ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance()); diff --git a/app/src/main/java/de/danoeh/antennapod/view/TimePicker.java b/app/src/main/java/de/danoeh/antennapod/view/TimePicker.java deleted file mode 100644 index 191f72d2e..000000000 --- a/app/src/main/java/de/danoeh/antennapod/view/TimePicker.java +++ /dev/null @@ -1,31 +0,0 @@ -package de.danoeh.antennapod.view; - -import android.content.Context; -import android.util.AttributeSet; - -/** - * Samsung's Android 6.0.1 has a bug that crashes the app when inflating a time picker. - * This class serves as a workaround for affected devices. - */ -public class TimePicker extends android.widget.TimePicker { - public TimePicker(Context context) { - super(context); - } - - public TimePicker(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public TimePicker(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - public void onRtlPropertiesChanged(int layoutDirection) { - try { - super.onRtlPropertiesChanged(layoutDirection); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/res/layout/feed_refresh_dialog.xml b/app/src/main/res/layout/feed_refresh_dialog.xml deleted file mode 100644 index 5a6770a80..000000000 --- a/app/src/main/res/layout/feed_refresh_dialog.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/scrollable_dialog.xml b/app/src/main/res/layout/scrollable_dialog.xml deleted file mode 100644 index 29b84ee4b..000000000 --- a/app/src/main/res/layout/scrollable_dialog.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - -