diff options
author | ByteHamster <ByteHamster@users.noreply.github.com> | 2023-05-05 23:09:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-05 23:09:03 +0200 |
commit | 6d7bfef8a5fe8180f13904739996bb2b8de8a0d4 (patch) | |
tree | 84f246b74fe7254678788e9f206d81d1a30ffa5e /app/src | |
parent | 4c286931cd2dbd9038022f808f9d8a73ccbb6759 (diff) | |
download | AntennaPod-6d7bfef8a5fe8180f13904739996bb2b8de8a0d4.zip |
Download Service Rewrite (#6420)
Diffstat (limited to 'app/src')
33 files changed, 212 insertions, 889 deletions
diff --git a/app/src/androidTest/java/de/danoeh/antennapod/core/service/download/StubDownloader.java b/app/src/androidTest/java/de/danoeh/antennapod/core/service/download/StubDownloader.java index 302301c85..835af1f95 100644 --- a/app/src/androidTest/java/de/danoeh/antennapod/core/service/download/StubDownloader.java +++ b/app/src/androidTest/java/de/danoeh/antennapod/core/service/download/StubDownloader.java @@ -2,7 +2,7 @@ package de.danoeh.antennapod.core.service.download; import androidx.annotation.NonNull; import androidx.core.util.Consumer; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; public class StubDownloader extends Downloader { @@ -10,9 +10,10 @@ public class StubDownloader extends Downloader { private final long downloadTime; @NonNull - private final Consumer<DownloadStatus> onDownloadComplete; + private final Consumer<DownloadResult> onDownloadComplete; - public StubDownloader(@NonNull DownloadRequest request, long downloadTime, @NonNull Consumer<DownloadStatus> onDownloadComplete) { + public StubDownloader(@NonNull DownloadRequest request, long downloadTime, + @NonNull Consumer<DownloadResult> onDownloadComplete) { super(request); this.downloadTime = downloadTime; this.onDownloadComplete = onDownloadComplete; @@ -36,7 +37,7 @@ public class StubDownloader extends Downloader { @NonNull @Override - public DownloadStatus getResult() { + public DownloadResult getResult() { return super.getResult(); } diff --git a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java index d65289638..a7575862b 100644 --- a/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java +++ b/app/src/androidTest/java/de/test/antennapod/EspressoTestUtils.java @@ -24,7 +24,6 @@ import junit.framework.AssertionFailedError; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.dialog.RatingDialog; import de.danoeh.antennapod.fragment.NavDrawerFragment; @@ -224,21 +223,6 @@ public class EspressoTestUtils { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } - public static void tryKillDownloadService() { - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - context.stopService(new Intent(context, DownloadService.class)); - try { - // Android has no reliable way to stop a service instantly. - // Calling stopSelf marks allows the system to destroy the service but the actual call - // to onDestroy takes until the next GC of the system, which we can not influence. - // Try to wait for the service at least a bit. - Awaitility.await().atMost(10, TimeUnit.SECONDS).until(() -> !DownloadService.isRunning); - } catch (ConditionTimeoutException e) { - e.printStackTrace(); - } - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); - } - public static Matcher<View> actionBarOverflow() { return allOf(isDisplayed(), withContentDescription("More options")); } diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java deleted file mode 100644 index 97499b24a..000000000 --- a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java +++ /dev/null @@ -1,217 +0,0 @@ -package de.test.antennapod.service.download; - -import android.content.Context; -import android.content.Intent; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.util.Consumer; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; -import de.test.antennapod.EspressoTestUtils; -import org.awaitility.Awaitility; -import org.awaitility.core.ConditionTimeoutException; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.model.feed.FeedMedia; -import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadService; -import de.danoeh.antennapod.model.download.DownloadStatus; -import de.danoeh.antennapod.core.service.download.Downloader; -import de.danoeh.antennapod.core.service.download.DownloaderFactory; -import de.danoeh.antennapod.core.service.download.StubDownloader; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; - -import static de.test.antennapod.util.event.DownloadEventListener.withDownloadEventListener; -import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @see HttpDownloaderTest for the test of actual download (and saving the file). - */ -@RunWith(AndroidJUnit4.class) -public class DownloadServiceTest { - private FeedMedia testMedia11 = null; - - private DownloaderFactory origFactory = null; - - @Before - public void setUp() throws Exception { - EspressoTestUtils.clearDatabase(); - EspressoTestUtils.clearPreferences(); - origFactory = DownloadService.getDownloaderFactory(); - Feed testFeed = setUpTestFeeds(); - testMedia11 = testFeed.getItemAtIndex(0).getMedia(); - } - - private Feed setUpTestFeeds() throws Exception { - // To avoid complication in case of test failures, leaving behind orphaned - // media files: add a timestamp so that each test run will have its own directory for media files. - Feed feed = new Feed("url", null, "Test Feed title 1 " + System.currentTimeMillis()); - List<FeedItem> items = new ArrayList<>(); - feed.setItems(items); - FeedItem item1 = new FeedItem(0, "Item 1-1", "Item 1-1", "url", new Date(), FeedItem.NEW, feed); - items.add(item1); - FeedMedia media1 = new FeedMedia(0, item1, 123, 1, 1, "audio/mp3", null, "http://example.com/episode.mp3", false, null, 0, 0); - item1.setMedia(media1); - - DBWriter.setFeedItem(item1).get(); - return feed; - } - - - @After - public void tearDown() throws Exception { - DownloadService.setDownloaderFactory(origFactory); - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - DownloadServiceInterface.get().cancelAll(context); - context.stopService(new Intent(context, DownloadService.class)); - EspressoTestUtils.tryKillDownloadService(); - } - - @Test - public void testEventsGeneratedCaseMediaDownloadSuccess_noEnqueue() throws Exception { - doTestEventsGeneratedCaseMediaDownloadSuccess(false, 1); - } - - @Test - public void testEventsGeneratedCaseMediaDownloadSuccess_withEnqueue() throws Exception { - // enqueue itself generates additional FeedItem event - doTestEventsGeneratedCaseMediaDownloadSuccess(true, 2); - } - - private void doTestEventsGeneratedCaseMediaDownloadSuccess(boolean enqueueDownloaded, - int numEventsExpected) - throws Exception { - // create a stub download that returns successful - // - // OPEN: Ideally, I'd like the download time long enough so that multiple in-progress DownloadEvents - // are generated (to simulate typical download), but it'll make download time quite long (1-2 seconds) - // to do so - DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, DownloadStatus::setSuccessful)); - - UserPreferences.setEnqueueDownloadedEpisodes(enqueueDownloaded); - withFeedItemEventListener(feedItemEventListener -> { - try { - assertEquals(0, feedItemEventListener.getEvents().size()); - assertFalse("The media in test should not yet been downloaded", - DBReader.getFeedMedia(testMedia11.getId()).isDownloaded()); - - DownloadServiceInterface.get() - .download(InstrumentationRegistry.getInstrumentation().getTargetContext(), false, - DownloadRequestCreator.create(testMedia11).build()); - Awaitility.await() - .atMost(5000, TimeUnit.MILLISECONDS) - .until(() -> feedItemEventListener.getEvents().size() >= numEventsExpected); - assertTrue("After media download has completed, FeedMedia object in db should indicate so.", - DBReader.getFeedMedia(testMedia11.getId()).isDownloaded()); - assertEquals("The FeedItem should have been " + (enqueueDownloaded ? "" : "not ") + "enqueued", - enqueueDownloaded, - DBReader.getQueueIDList().contains(testMedia11.getItem().getId())); - } catch (ConditionTimeoutException cte) { - fail("The expected FeedItemEvent (for media download complete) has not been posted. " - + cte.getMessage()); - } - }); - } - - @Test - public void testCancelDownload_UndoEnqueue_Normal() throws Exception { - doTestCancelDownload_UndoEnqueue(false); - } - - @Test - public void testCancelDownload_UndoEnqueue_AlreadyInQueue() throws Exception { - doTestCancelDownload_UndoEnqueue(true); - } - - private void doTestCancelDownload_UndoEnqueue(boolean itemAlreadyInQueue) throws Exception { - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - // let download take longer to ensure the test can cancel the download in time - DownloadService.setDownloaderFactory( - new StubDownloaderFactory(30000, DownloadStatus::setSuccessful)); - UserPreferences.setEnqueueDownloadedEpisodes(true); - UserPreferences.setEnableAutodownload(false); - - final long item1Id = testMedia11.getItem().getId(); - if (itemAlreadyInQueue) { - // simulate item already in queue condition - DBWriter.addQueueItem(context, false, item1Id).get(); - assertTrue(DBReader.getQueueIDList().contains(item1Id)); - } else { - assertFalse(DBReader.getQueueIDList().contains(item1Id)); - } - - withFeedItemEventListener(feedItemEventListener -> { - DownloadServiceInterface.get() - .download(InstrumentationRegistry.getInstrumentation().getTargetContext(), false, - DownloadRequestCreator.create(testMedia11).build()); - withDownloadEventListener(downloadEventListener -> - Awaitility.await("download is actually running") - .atMost(5000, TimeUnit.MILLISECONDS) - .until(() -> downloadEventListener.getLatestEvent() != null - && downloadEventListener.getLatestEvent().update.mediaIds.length > 0 - && downloadEventListener.getLatestEvent().update.mediaIds[0] == testMedia11.getId())); - - if (itemAlreadyInQueue) { - assertEquals("download service receives the request - no event is expected before cancel is issued", - 0, feedItemEventListener.getEvents().size()); - } else { - Awaitility.await("item enqueue event") - .atMost(2000, TimeUnit.MILLISECONDS) - .until(() -> feedItemEventListener.getEvents().size() >= 1); - } - DownloadServiceInterface.get().cancel(context, testMedia11.getDownload_url()); - final int totalNumEventsExpected = itemAlreadyInQueue ? 1 : 3; - Awaitility.await("item dequeue event + download termination event") - .atMost(2000, TimeUnit.MILLISECONDS) - .until(() -> feedItemEventListener.getEvents().size() >= totalNumEventsExpected); - assertFalse("The download should have been canceled", - DBReader.getFeedMedia(testMedia11.getId()).isDownloaded()); - if (itemAlreadyInQueue) { - assertTrue("The FeedItem should still be in the queue after the download is cancelled." - + " It's there before download.", - DBReader.getQueueIDList().contains(item1Id)); - } else { - assertFalse("The FeedItem should not be in the queue after the download is cancelled.", - DBReader.getQueueIDList().contains(item1Id)); - } - }); - } - - private static class StubDownloaderFactory implements DownloaderFactory { - private final long downloadTime; - - @NonNull - private final Consumer<DownloadStatus> onDownloadComplete; - - StubDownloaderFactory(long downloadTime, @NonNull Consumer<DownloadStatus> onDownloadComplete) { - this.downloadTime = downloadTime; - this.onDownloadComplete = onDownloadComplete; - } - - @Nullable - @Override - public Downloader create(@NonNull DownloadRequest request) { - return new StubDownloader(request, downloadTime, onDownloadComplete); - } - } - -} diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java index f276434f6..76cba4706 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/download/HttpDownloaderTest.java @@ -10,7 +10,7 @@ import java.io.IOException; import de.danoeh.antennapod.model.feed.FeedFile; import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.model.download.DownloadError; @@ -80,10 +80,9 @@ public class HttpDownloaderTest { DownloadRequest request = new DownloadRequest(feedFile.getFile_url(), url, title, 0, feedFile.getTypeAsInt(), username, password, deleteOnFail, null, false); Downloader downloader = new HttpDownloader(request); downloader.call(); - DownloadStatus status = downloader.getResult(); + DownloadResult status = downloader.getResult(); assertNotNull(status); assertEquals(expectedResult, status.isSuccessful()); - assertTrue(status.isDone()); // the file should not exist if the download has failed and deleteExisting was true assertTrue(!deleteExisting || new File(feedFile.getFile_url()).exists() == expectedResult); return downloader; @@ -127,10 +126,8 @@ public class HttpDownloaderTest { } catch (InterruptedException e) { e.printStackTrace(); } - DownloadStatus result = downloader.getResult(); - assertTrue(result.isDone()); + DownloadResult result = downloader.getResult(); assertFalse(result.isSuccessful()); - assertTrue(result.isCancelled()); assertFalse(new File(feedFile.getFile_url()).exists()); } 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 5940d511b..1f387b24b 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -27,8 +27,6 @@ import java.util.Arrays; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard; -import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.action.ViewActions.scrollTo; import static androidx.test.espresso.action.ViewActions.swipeDown; import static androidx.test.espresso.action.ViewActions.swipeUp; @@ -37,13 +35,11 @@ import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isChecked; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isRoot; -import static androidx.test.espresso.matcher.ViewMatchers.withClassName; import static androidx.test.espresso.matcher.ViewMatchers.withId; 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.endsWith; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertTrue; @@ -224,40 +220,6 @@ public class PreferencesTest { } @Test - public void testSetSequentialDownload() { - clickPreference(R.string.downloads_pref); - clickPreference(R.string.pref_parallel_downloads_title); - onView(isRoot()).perform(waitForView(withClassName(endsWith("EditText")), 1000)); - onView(withClassName(endsWith("EditText"))).perform(replaceText("1")); - onView(withText(android.R.string.ok)).perform(click()); - Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getParallelDownloads() == 1); - } - - @Test - public void testSetParallelDownloads() { - clickPreference(R.string.downloads_pref); - clickPreference(R.string.pref_parallel_downloads_title); - onView(isRoot()).perform(waitForView(withClassName(endsWith("EditText")), 1000)); - onView(withClassName(endsWith("EditText"))).perform(replaceText("10")); - onView(withClassName(endsWith("EditText"))).perform(closeSoftKeyboard()); - onView(withText(android.R.string.ok)).perform(click()); - Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getParallelDownloads() == 10); - } - - @Test - public void testSetParallelDownloadsInvalidInput() { - clickPreference(R.string.downloads_pref); - clickPreference(R.string.pref_parallel_downloads_title); - onView(isRoot()).perform(waitForView(withClassName(endsWith("EditText")), 1000)); - onView(withClassName(endsWith("EditText"))).perform(replaceText("0")); - onView(withClassName(endsWith("EditText"))).check(matches(withText(""))); - onView(withClassName(endsWith("EditText"))).perform(replaceText("100")); - onView(withClassName(endsWith("EditText"))).check(matches(withText(""))); - } - - @Test public void testSetEpisodeCache() { String[] entries = res.getStringArray(R.array.episode_cache_size_entries); String[] values = res.getStringArray(R.array.episode_cache_size_values); diff --git a/app/src/androidTest/java/de/test/antennapod/util/event/DownloadEventListener.java b/app/src/androidTest/java/de/test/antennapod/util/event/DownloadEventListener.java deleted file mode 100644 index d322c1cbf..000000000 --- a/app/src/androidTest/java/de/test/antennapod/util/event/DownloadEventListener.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.test.antennapod.util.event; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import de.danoeh.antennapod.core.event.DownloadEvent; -import io.reactivex.functions.Consumer; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; - -import java.util.ArrayList; -import java.util.List; - -/** - * Test helper to listen to {@link DownloadEvent} and handle them accordingly. - */ -public class DownloadEventListener { - private final List<DownloadEvent> events = new ArrayList<>(); - - /** - * Provides an listener subscribing to {@link DownloadEvent} that the callers can use. - * Note: it uses RxJava's version of {@link Consumer} because it allows exceptions to be thrown. - */ - public static void withDownloadEventListener(@NonNull Consumer<DownloadEventListener> consumer) throws Exception { - DownloadEventListener feedItemEventListener = new DownloadEventListener(); - try { - EventBus.getDefault().register(feedItemEventListener); - consumer.accept(feedItemEventListener); - } finally { - EventBus.getDefault().unregister(feedItemEventListener); - } - } - - @Subscribe - public void onEvent(DownloadEvent event) { - events.add(event); - } - - @Nullable - public DownloadEvent getLatestEvent() { - if (events.size() == 0) { - return null; - } - return events.get(events.size() - 1); - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8c779db26..95b0c1614 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -130,17 +130,6 @@ </activity> <activity - android:name=".activity.DownloadAuthenticationActivity" - android:theme="@style/Theme.AntennaPod.Dark.Translucent" - android:exported="false" - android:launchMode="singleInstance"> - <intent-filter> - <action android:name="de.danoeh.antennapod.intents.DOWNLOAD_AUTH_ACTIVITY" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - - <activity android:name=".activity.PreferenceActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="false" diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java deleted file mode 100644 index 176c3c990..000000000 --- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java +++ /dev/null @@ -1,71 +0,0 @@ -package de.danoeh.antennapod.activity; - -import android.os.Bundle; -import android.text.TextUtils; -import androidx.appcompat.app.AppCompatActivity; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.preferences.ThemeSwitcher; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; -import de.danoeh.antennapod.model.feed.FeedMedia; -import de.danoeh.antennapod.model.feed.FeedPreferences; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.dialog.AuthenticationDialog; -import de.danoeh.antennapod.ui.appstartintent.DownloadAuthenticationActivityStarter; -import io.reactivex.Completable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; - - -/** - * Shows a username and a password text field. - * The activity MUST be started with the ARG_DOWNlOAD_REQUEST argument set to a non-null value. - */ -public class DownloadAuthenticationActivity extends AppCompatActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - setTheme(ThemeSwitcher.getTranslucentTheme(this)); - super.onCreate(savedInstanceState); - - DownloadRequest request = getIntent().getParcelableExtra( - DownloadAuthenticationActivityStarter.EXTRA_DOWNLOAD_REQUEST); - - new AuthenticationDialog(this, R.string.authentication_label, true, "", "") { - @Override - protected void onConfirmed(String username, String password) { - Completable.fromAction( - () -> { - request.setUsername(username); - request.setPassword(password); - - if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - long mediaId = request.getFeedfileId(); - FeedMedia media = DBReader.getFeedMedia(mediaId); - if (media != null) { - FeedPreferences preferences = media.getItem().getFeed().getPreferences(); - if (TextUtils.isEmpty(preferences.getPassword()) - || TextUtils.isEmpty(preferences.getUsername())) { - preferences.setUsername(username); - preferences.setPassword(password); - DBWriter.setFeedPreferences(preferences); - } - } - } - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(() -> { - DownloadServiceInterface.get() - .download(DownloadAuthenticationActivity.this, false, request); - finish(); - }); - } - - @Override - protected void onCancelled() { - finish(); - } - }.show(); - } -} 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 bd467076a..a55bfade3 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -39,12 +39,14 @@ import de.danoeh.antennapod.core.preferences.ThemeSwitcher; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.util.download.FeedUpdateManager; import de.danoeh.antennapod.dialog.RatingDialog; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; 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.DownloadLogFragment; import de.danoeh.antennapod.fragment.FeedItemlistFragment; import de.danoeh.antennapod.fragment.InboxFragment; import de.danoeh.antennapod.fragment.NavDrawerFragment; @@ -53,6 +55,8 @@ import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SearchFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.fragment.TransitionEffect; +import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.playback.cast.CastEnabledActivity; import de.danoeh.antennapod.preferences.PreferenceUpgrader; import de.danoeh.antennapod.storage.preferences.UserPreferences; @@ -66,6 +70,9 @@ import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import java.util.HashMap; +import java.util.Map; + /** * The activity that is shown when the user launches the app. */ @@ -173,6 +180,39 @@ public class MainActivity extends CastEnabledActivity { } EventBus.getDefault().postSticky(new FeedUpdateRunningEvent(isRefreshingFeeds)); }); + WorkManager.getInstance(this) + .getWorkInfosByTagLiveData(DownloadServiceInterface.WORK_TAG) + .observe(this, workInfos -> { + Map<String, DownloadStatus> updatedEpisodes = new HashMap<>(); + for (WorkInfo workInfo : workInfos) { + String downloadUrl = null; + for (String tag : workInfo.getTags()) { + if (tag.startsWith(DownloadServiceInterface.WORK_TAG_EPISODE_URL)) { + downloadUrl = tag.substring(DownloadServiceInterface.WORK_TAG_EPISODE_URL.length()); + } + } + if (downloadUrl == null) { + continue; + } + int status; + if (workInfo.getState() == WorkInfo.State.RUNNING) { + status = DownloadStatus.STATE_RUNNING; + } else if (workInfo.getState() == WorkInfo.State.ENQUEUED + || workInfo.getState() == WorkInfo.State.BLOCKED) { + status = DownloadStatus.STATE_QUEUED; + } else { + status = DownloadStatus.STATE_COMPLETED; + } + int progress = workInfo.getProgress().getInt(DownloadServiceInterface.WORK_DATA_PROGRESS, -1); + if (progress == -1 && status != DownloadStatus.STATE_COMPLETED) { + status = DownloadStatus.STATE_QUEUED; + progress = 0; + } + updatedEpisodes.put(downloadUrl, new DownloadStatus(status, progress)); + } + DownloadServiceInterface.get().setCurrentDownloads(updatedEpisodes); + EventBus.getDefault().postSticky(new EpisodeDownloadEvent(updatedEpisodes)); + }); } @Override @@ -531,9 +571,9 @@ public class MainActivity extends CastEnabledActivity { public void onEventMainThread(MessageEvent event) { Log.d(TAG, "onEvent(" + event + ")"); - Snackbar snackbar = showSnackbarAbovePlayer(event.message, Snackbar.LENGTH_SHORT); + Snackbar snackbar = showSnackbarAbovePlayer(event.message, Snackbar.LENGTH_LONG); if (event.action != null) { - snackbar.setAction(getString(R.string.undo), v -> event.action.run()); + snackbar.setAction(event.actionText, v -> event.action.accept(this)); } } @@ -570,6 +610,9 @@ public class MainActivity extends CastEnabledActivity { if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_DRAWER, false) && drawerLayout != null) { drawerLayout.open(); } + if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_DOWNLOAD_LOGS, false)) { + new DownloadLogFragment().show(getSupportFragmentManager(), null); + } if (intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false)) { FeedUpdateManager.runOnceOrAsk(this); } 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 f5f3d28f6..3812339bd 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -31,20 +31,20 @@ import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter; -import de.danoeh.antennapod.core.event.DownloadEvent; 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.core.storage.DBTasks; import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface; import de.danoeh.antennapod.core.util.DownloadErrorLabel; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; @@ -307,10 +307,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { error -> Log.e(TAG, Log.getStackTraceString(error))); } - private void checkDownloadResult(@NonNull DownloadStatus status, String destination) { - if (status.isCancelled()) { - return; - } + private void checkDownloadResult(@NonNull DownloadResult status, String destination) { if (status.isSuccessful()) { parseFeed(destination); } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) { @@ -341,9 +338,8 @@ public class OnlineFeedViewActivity extends AppCompatActivity { ); } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + public void onEventMainThread(EpisodeDownloadEvent event) { handleUpdatedFeedStatus(); } @@ -535,7 +531,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } private void handleUpdatedFeedStatus() { - if (DownloadService.isDownloadingFile(selectedDownloadUrl)) { + if (DownloadServiceInterface.get().isDownloadingEpisode(selectedDownloadUrl)) { viewBinding.subscribeButton.setEnabled(false); viewBinding.subscribeButton.setText(R.string.subscribing_label); } else if (feedInFeedlist()) { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java index 8df3e3968..0fb6a7e7a 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java @@ -2,7 +2,6 @@ package de.danoeh.antennapod.adapter; import android.app.Activity; import android.text.format.DateUtils; -import android.text.format.Formatter; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -10,18 +9,13 @@ import android.widget.BaseAdapter; import android.widget.Toast; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; -import de.danoeh.antennapod.core.service.download.Downloader; +import de.danoeh.antennapod.adapter.actionbutton.DownloadActionButton; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; -import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.DownloadErrorLabel; import de.danoeh.antennapod.model.download.DownloadError; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.ui.common.ThemeUtils; import de.danoeh.antennapod.view.viewholder.DownloadLogItemViewHolder; @@ -36,24 +30,18 @@ public class DownloadLogAdapter extends BaseAdapter { private static final String TAG = "DownloadLogAdapter"; private final Activity context; - private List<DownloadStatus> downloadLog = new ArrayList<>(); - private List<Downloader> runningDownloads = new ArrayList<>(); + private List<DownloadResult> downloadLog = new ArrayList<>(); public DownloadLogAdapter(Activity context) { super(); this.context = context; } - public void setDownloadLog(List<DownloadStatus> downloadLog) { + public void setDownloadLog(List<DownloadResult> downloadLog) { this.downloadLog = downloadLog; notifyDataSetChanged(); } - public void setRunningDownloads(List<Downloader> runningDownloads) { - this.runningDownloads = runningDownloads; - notifyDataSetChanged(); - } - @Override public View getView(int position, View convertView, ViewGroup parent) { DownloadLogItemViewHolder holder; @@ -63,17 +51,11 @@ public class DownloadLogAdapter extends BaseAdapter { } else { holder = (DownloadLogItemViewHolder) convertView.getTag(); } - - Object item = getItem(position); - if (item instanceof DownloadStatus) { - bind(holder, (DownloadStatus) item, position); - } else if (item instanceof Downloader) { - bind(holder, (Downloader) item, position); - } + bind(holder, getItem(position), position); return holder.itemView; } - private void bind(DownloadLogItemViewHolder holder, DownloadStatus status, int position) { + private void bind(DownloadLogItemViewHolder holder, DownloadResult status, int position) { String statusText = ""; if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { statusText += context.getString(R.string.download_type_feed); @@ -111,8 +93,7 @@ public class DownloadLogAdapter extends BaseAdapter { holder.reason.setVisibility(View.VISIBLE); holder.tapForDetails.setVisibility(View.VISIBLE); - if (newerWasSuccessful(position - runningDownloads.size(), - status.getFeedfileType(), status.getFeedfileId())) { + if (newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) { holder.secondaryActionButton.setVisibility(View.INVISIBLE); holder.secondaryActionButton.setOnClickListener(null); holder.secondaryActionButton.setTag(null); @@ -138,8 +119,7 @@ public class DownloadLogAdapter extends BaseAdapter { Log.e(TAG, "Could not find feed media for feed id: " + status.getFeedfileId()); return; } - DownloadServiceInterface.get() - .download(context, true, DownloadRequestCreator.create(media).build()); + new DownloadActionButton(media.getItem()).onClick(context); ((MainActivity) context).showSnackbarAbovePlayer( R.string.status_downloading_label, Toast.LENGTH_SHORT); }); @@ -148,56 +128,9 @@ public class DownloadLogAdapter extends BaseAdapter { } } - private void bind(DownloadLogItemViewHolder holder, Downloader downloader, int position) { - DownloadRequest request = downloader.getDownloadRequest(); - holder.title.setText(request.getTitle()); - holder.secondaryActionIcon.setImageResource(R.drawable.ic_cancel); - holder.secondaryActionButton.setContentDescription(context.getString(R.string.cancel_download_label)); - holder.secondaryActionButton.setVisibility(View.VISIBLE); - holder.secondaryActionButton.setTag(downloader); - holder.secondaryActionButton.setOnClickListener(v -> { - DownloadServiceInterface.get().cancel(context, request.getSource()); - if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - FeedMedia media = DBReader.getFeedMedia(request.getFeedfileId()); - FeedItem feedItem = media.getItem(); - feedItem.disableAutoDownload(); - DBWriter.setFeedItem(feedItem); - } - }); - holder.reason.setVisibility(View.GONE); - holder.tapForDetails.setVisibility(View.GONE); - holder.icon.setTextColor(ThemeUtils.getColorFromAttr(context, R.attr.colorPrimary)); - holder.icon.setText("{fa-arrow-circle-down}"); - holder.icon.setContentDescription(context.getString(R.string.status_downloading_label)); - - boolean percentageWasSet = false; - String status = ""; - if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { - status += context.getString(R.string.download_type_feed); - } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - status += context.getString(R.string.download_type_media); - } - status += " · "; - if (request.getSoFar() <= 0) { - status += context.getString(R.string.download_pending); - } else { - status += Formatter.formatShortFileSize(context, request.getSoFar()); - if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) { - status += " / " + Formatter.formatShortFileSize(context, request.getSize()); - holder.secondaryActionProgress.setPercentage( - 0.01f * Math.max(1, request.getProgressPercent()), request); - percentageWasSet = true; - } - } - if (!percentageWasSet) { - holder.secondaryActionProgress.setPercentage(0, request); - } - holder.status.setText(status); - } - private boolean newerWasSuccessful(int downloadStatusIndex, int feedTypeId, long id) { for (int i = 0; i < downloadStatusIndex; i++) { - DownloadStatus status = downloadLog.get(i); + DownloadResult status = downloadLog.get(i); if (status.getFeedfileType() == feedTypeId && status.getFeedfileId() == id && status.isSuccessful()) { return true; } @@ -207,15 +140,13 @@ public class DownloadLogAdapter extends BaseAdapter { @Override public int getCount() { - return downloadLog.size() + runningDownloads.size(); + return downloadLog.size(); } @Override - public Object getItem(int position) { - if (position < runningDownloads.size()) { - return runningDownloads.get(position); - } else if (position - runningDownloads.size() < downloadLog.size()) { - return downloadLog.get(position - runningDownloads.size()); + public DownloadResult getItem(int position) { + if (position < downloadLog.size()) { + return downloadLog.get(position); } return null; } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java index 3b54efc03..86a8047a9 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java @@ -2,20 +2,17 @@ package de.danoeh.antennapod.adapter.actionbutton; import android.content.Context; import android.view.View; -import android.widget.Toast; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.StringRes; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UsageStatistics; -import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.NetworkUtils; public class DownloadActionButton extends ItemActionButton { @@ -50,19 +47,23 @@ public class DownloadActionButton extends ItemActionButton { UsageStatistics.logAction(UsageStatistics.ACTION_DOWNLOAD); - if (NetworkUtils.isEpisodeDownloadAllowed() || MobileDownloadHelper.userAllowedMobileDownloads()) { - DownloadServiceInterface.get() - .download(context, false, DownloadRequestCreator.create(item.getMedia()).build()); - } else if (MobileDownloadHelper.userChoseAddToQueue() && !item.isTagged(FeedItem.TAG_QUEUE)) { - DBWriter.addQueueItem(context, item); - Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show(); + if (NetworkUtils.isEpisodeDownloadAllowed()) { + DownloadServiceInterface.get().downloadNow(context, item, false); } else { - MobileDownloadHelper.confirmMobileDownload(context, item); + MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context) + .setTitle(R.string.confirm_mobile_download_dialog_title) + .setMessage(R.string.confirm_mobile_download_dialog_message) + .setPositiveButton(R.string.confirm_mobile_download_dialog_download_later, + (d, w) -> DownloadServiceInterface.get().downloadNow(context, item, false)) + .setNeutralButton(R.string.confirm_mobile_download_dialog_allow_this_time, + (d, w) -> DownloadServiceInterface.get().downloadNow(context, item, true)) + .setNegativeButton(R.string.cancel_label, null); + builder.show(); } } private boolean shouldNotDownload(@NonNull FeedMedia media) { - boolean isDownloading = DownloadService.isDownloadingFile(media.getDownload_url()); + boolean isDownloading = DownloadServiceInterface.get().isDownloadingEpisode(media.getDownload_url()); return isDownloading || media.isDownloaded(); } } diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java index e7a95c404..613dd32f0 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/ItemActionButton.java @@ -7,10 +7,10 @@ import androidx.annotation.NonNull; import androidx.annotation.StringRes; import android.view.View; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.util.PlaybackStatus; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; +import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.storage.preferences.UserPreferences; public abstract class ItemActionButton { @@ -39,7 +39,7 @@ public abstract class ItemActionButton { return new MarkAsPlayedActionButton(item); } - final boolean isDownloadingMedia = DownloadService.isDownloadingFile(media.getDownload_url()); + final boolean isDownloadingMedia = DownloadServiceInterface.get().isDownloadingEpisode(media.getDownload_url()); if (PlaybackStatus.isCurrentlyPlaying(media)) { return new PauseActionButton(item); } else if (item.getFeed().isLocalFeed()) { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java deleted file mode 100644 index 015f46318..000000000 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.danoeh.antennapod.adapter.actionbutton; - -import android.content.Context; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; -import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; - -class MobileDownloadHelper { - private static long addToQueueTimestamp; - private static long allowMobileDownloadTimestamp; - private static final int TEN_MINUTES_IN_MILLIS = 10 * 60 * 1000; - - static boolean userChoseAddToQueue() { - return System.currentTimeMillis() - addToQueueTimestamp < TEN_MINUTES_IN_MILLIS; - } - - static boolean userAllowedMobileDownloads() { - return System.currentTimeMillis() - allowMobileDownloadTimestamp < TEN_MINUTES_IN_MILLIS; - } - - static void confirmMobileDownload(final Context context, final FeedItem item) { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context) - .setTitle(R.string.confirm_mobile_download_dialog_title) - .setMessage(R.string.confirm_mobile_download_dialog_message) - .setPositiveButton(context.getText(R.string.confirm_mobile_download_dialog_enable_temporarily), - (dialog, which) -> downloadFeedItems(context, item)); - if (!DBReader.getQueueIDList().contains(item.getId())) { - builder.setMessage(R.string.confirm_mobile_download_dialog_message_not_in_queue) - .setNeutralButton(R.string.confirm_mobile_download_dialog_only_add_to_queue, - (dialog, which) -> addToQueue(context, item)); - } - builder.show(); - } - - private static void addToQueue(Context context, FeedItem item) { - addToQueueTimestamp = System.currentTimeMillis(); - DBWriter.addQueueItem(context, item); - } - - private static void downloadFeedItems(Context context, FeedItem item) { - allowMobileDownloadTimestamp = System.currentTimeMillis(); - DownloadServiceInterface.get().download(context, true, DownloadRequestCreator.create(item.getMedia()).build()); - } -}
\ No newline at end of file diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/DownloadLogDetailsDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/DownloadLogDetailsDialog.java index 5e28639dd..00936a38a 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/DownloadLogDetailsDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/DownloadLogDetailsDialog.java @@ -9,7 +9,7 @@ import androidx.appcompat.app.AlertDialog; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.util.DownloadErrorLabel; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.event.MessageEvent; import de.danoeh.antennapod.model.feed.Feed; @@ -18,7 +18,7 @@ import org.greenrobot.eventbus.EventBus; public class DownloadLogDetailsDialog extends MaterialAlertDialogBuilder { - public DownloadLogDetailsDialog(@NonNull Context context, DownloadStatus status) { + public DownloadLogDetailsDialog(@NonNull Context context, DownloadResult status) { super(context); String url = "unknown"; 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 737975389..ba328adba 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -20,12 +20,12 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; import de.danoeh.antennapod.adapter.actionbutton.DeleteActionButton; -import de.danoeh.antennapod.core.event.DownloadEvent; 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.FeedUpdateManager; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; @@ -36,6 +36,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.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; @@ -50,9 +51,10 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Displays all completed downloads and provides a button to delete them. @@ -63,7 +65,7 @@ public class CompletedDownloadsFragment extends Fragment public static final String ARG_SHOW_LOGS = "show_logs"; private static final String KEY_UP_ARROW = "up_arrow"; - private long[] runningDownloads = new long[0]; + private Set<String> runningDownloads = new HashSet<>(); private List<FeedItem> items = new ArrayList<>(); private CompletedDownloadsListAdapter adapter; private EpisodeItemListRecyclerView recyclerView; @@ -217,19 +219,22 @@ public class CompletedDownloadsFragment extends Fragment } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - if (!Arrays.equals(event.update.mediaIds, runningDownloads)) { - runningDownloads = event.update.mediaIds; + public void onEventMainThread(EpisodeDownloadEvent event) { + Set<String> newRunningDownloads = new HashSet<>(); + for (String url : event.getUrls()) { + if (DownloadServiceInterface.get().isDownloadingEpisode(url)) { + newRunningDownloads.add(url); + } + } + if (!newRunningDownloads.equals(runningDownloads)) { + runningDownloads = newRunningDownloads; loadItems(); return; // Refreshed anyway } - if (event.update.mediaIds.length > 0) { - for (long mediaId : event.update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(items, mediaId); - if (pos >= 0) { - adapter.notifyItemChangedCompat(pos); - } + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(items, downloadUrl); + if (pos >= 0) { + adapter.notifyItemChangedCompat(pos); } } } @@ -318,17 +323,17 @@ public class CompletedDownloadsFragment extends Fragment List<FeedItem> downloadedItems = DBReader.getEpisodes(0, Integer.MAX_VALUE, new FeedItemFilter(FeedItemFilter.DOWNLOADED), sortOrder); - List<Long> mediaIds = new ArrayList<>(); + List<String> mediaUrls = new ArrayList<>(); if (runningDownloads == null) { return downloadedItems; } - for (long id : runningDownloads) { - if (FeedItemUtil.indexOfItemWithMediaId(downloadedItems, id) != -1) { + for (String url : runningDownloads) { + if (FeedItemUtil.indexOfItemWithDownloadUrl(downloadedItems, url) != -1) { continue; // Already in list } - mediaIds.add(id); + mediaUrls.add(url); } - List<FeedItem> currentDownloads = DBReader.getFeedItemsWithMedia(mediaIds.toArray(new Long[0])); + List<FeedItem> currentDownloads = DBReader.getFeedItemsWithUrl(mediaUrls); currentDownloads.addAll(downloadedItems); return currentDownloads; }) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index c27d8c058..03913ff12 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -14,15 +14,12 @@ import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.DownloadLogAdapter; -import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.event.DownloadLogEvent; -import de.danoeh.antennapod.core.event.DownloaderUpdate; -import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.databinding.DownloadLogFragmentBinding; import de.danoeh.antennapod.dialog.DownloadLogDetailsDialog; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.view.EmptyViewHandler; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -30,7 +27,6 @@ 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; import java.util.ArrayList; import java.util.List; @@ -42,8 +38,7 @@ public class DownloadLogFragment extends BottomSheetDialogFragment implements AdapterView.OnItemClickListener, MaterialToolbar.OnMenuItemClickListener { private static final String TAG = "DownloadLogFragment"; - private List<DownloadStatus> downloadLog = new ArrayList<>(); - private List<Downloader> runningDownloads = new ArrayList<>(); + private List<DownloadResult> downloadLog = new ArrayList<>(); private DownloadLogAdapter adapter; private Disposable disposable; private DownloadLogFragmentBinding viewBinding; @@ -93,8 +88,8 @@ public class DownloadLogFragment extends BottomSheetDialogFragment @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Object item = adapter.getItem(position); - if (item instanceof DownloadStatus) { - new DownloadLogDetailsDialog(getContext(), (DownloadStatus) item).show(); + if (item instanceof DownloadResult) { + new DownloadLogDetailsDialog(getContext(), (DownloadResult) item).show(); } } @@ -119,14 +114,6 @@ public class DownloadLogFragment extends BottomSheetDialogFragment return false; } - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEvent(DownloadEvent event) { - Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); - DownloaderUpdate update = event.update; - runningDownloads = update.downloaders; - adapter.setRunningDownloads(runningDownloads); - } - private void loadDownloadLog() { if (disposable != null) { disposable.dispose(); 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 ef784e9ee..00d671d36 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -27,11 +27,10 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; 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.util.FeedItemUtil; import de.danoeh.antennapod.core.util.download.FeedUpdateManager; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; import de.danoeh.antennapod.event.FeedUpdateRunningEvent; @@ -387,16 +386,11 @@ public abstract class EpisodesListFragment extends Fragment } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - DownloaderUpdate update = event.update; - updateToolbar(); - if (update.mediaIds.length > 0) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId); - if (pos >= 0) { - listAdapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(episodes, downloadUrl); + if (pos >= 0) { + listAdapter.notifyItemChangedCompat(pos); } } } 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 61883afe7..f59d5dbd4 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java @@ -29,8 +29,6 @@ import com.leinardi.android.speeddial.SpeedDialView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; -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.storage.DBReader; @@ -45,6 +43,7 @@ import de.danoeh.antennapod.dialog.DownloadLogDetailsDialog; import de.danoeh.antennapod.dialog.FeedItemFilterDialog; import de.danoeh.antennapod.dialog.RemoveFeedDialog; import de.danoeh.antennapod.dialog.RenameItemDialog; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FavoritesEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; @@ -57,7 +56,7 @@ import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler; import de.danoeh.antennapod.fragment.swipeactions.SwipeActions; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; -import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadResult; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedItemFilter; @@ -330,16 +329,14 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - DownloaderUpdate update = event.update; - updateToolbar(); - if (update.mediaIds.length > 0 && feed != null) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId); - if (pos >= 0) { - adapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + if (feed == null) { + return; + } + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(feed.getItems(), downloadUrl); + if (pos >= 0) { + adapter.notifyItemChangedCompat(pos); } } } @@ -479,7 +476,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem private void showErrorDetails() { Maybe.fromCallable( () -> { - List<DownloadStatus> feedDownloadLog = DBReader.getFeedDownloadLog(feedID); + List<DownloadResult> feedDownloadLog = DBReader.getFeedDownloadLog(feedID); if (feedDownloadLog.size() == 0 || feedDownloadLog.get(0).isSuccessful()) { return null; } @@ -490,9 +487,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem .subscribe( downloadStatus -> new DownloadLogDetailsDialog(getContext(), downloadStatus).show(), error -> error.printStackTrace(), - () -> { - ((MainActivity) getActivity()).loadChildFragment(new DownloadLogFragment()); - }); + () -> new DownloadLogFragment().show(getChildFragmentManager(), null)); } private void showFeedInfo() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index df48c9a98..94877811e 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -37,10 +37,7 @@ import de.danoeh.antennapod.adapter.actionbutton.PlayActionButton; import de.danoeh.antennapod.adapter.actionbutton.PlayLocalActionButton; import de.danoeh.antennapod.adapter.actionbutton.StreamActionButton; import de.danoeh.antennapod.adapter.actionbutton.VisitWebsiteActionButton; -import de.danoeh.antennapod.core.event.DownloadEvent; -import de.danoeh.antennapod.core.event.DownloaderUpdate; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.core.util.PlaybackStatus; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; @@ -49,8 +46,8 @@ import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.feed.util.ImageResourceUtils; import de.danoeh.antennapod.core.preferences.UsageStatistics; +import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DateFormatter; @@ -63,12 +60,10 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -import org.apache.commons.lang3.ArrayUtils; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import java.util.List; import java.util.Locale; import java.util.Objects; @@ -98,7 +93,6 @@ public class ItemFragment extends Fragment { private long itemId; private FeedItem item; private String webviewData; - private List<Downloader> downloaderList; private ViewGroup root; private ShownotesWebView webvDescription; @@ -309,14 +303,13 @@ public class ItemFragment extends Fragment { private void updateButtons() { progbarDownload.setVisibility(View.GONE); - if (item.hasMedia() && downloaderList != null) { - for (Downloader downloader : downloaderList) { - DownloadRequest request = downloader.getDownloadRequest(); - if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA - && request.getFeedfileId() == item.getMedia().getId()) { - progbarDownload.setVisibility(View.VISIBLE); - progbarDownload.setPercentage(0.01f * Math.max(1, request.getProgressPercent()), request); - } + if (item.hasMedia()) { + if (DownloadServiceInterface.get().isDownloadingEpisode(item.getMedia().getDownload_url())) { + progbarDownload.setVisibility(View.VISIBLE); + progbarDownload.setPercentage(0.01f * Math.max(1, + DownloadServiceInterface.get().getProgress(item.getMedia().getDownload_url())), item); + progbarDownload.setIndeterminate( + DownloadServiceInterface.get().isEpisodeQueued(item.getMedia().getDownload_url())); } } @@ -341,7 +334,7 @@ public class ItemFragment extends Fragment { } else { actionButton1 = new StreamActionButton(item); } - if (DownloadService.isDownloadingFile(media.getDownload_url())) { + if (DownloadServiceInterface.get().isDownloadingEpisode(media.getDownload_url())) { actionButton2 = new CancelDownloadActionButton(item); } else if (!media.isDownloaded()) { actionButton2 = new DownloadActionButton(item); @@ -386,18 +379,15 @@ public class ItemFragment extends Fragment { } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - DownloaderUpdate update = event.update; - downloaderList = update.downloaders; + public void onEventMainThread(EpisodeDownloadEvent event) { if (item == null || item.getMedia() == null) { return; } - long mediaId = item.getMedia().getId(); - if (ArrayUtils.contains(update.mediaIds, mediaId)) { - if (itemsLoaded && getActivity() != null) { - updateButtons(); - } + if (!event.getUrls().contains(item.getMedia().getDownload_url())) { + return; + } + if (itemsLoaded && getActivity() != null) { + updateButtons(); } } 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 6681df4c1..a1aa7226d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java @@ -32,8 +32,6 @@ import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; import de.danoeh.antennapod.adapter.QueueRecyclerAdapter; 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.feed.util.PlaybackSpeedUtils; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; import de.danoeh.antennapod.core.storage.DBReader; @@ -41,6 +39,7 @@ 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.FeedUpdateManager; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedUpdateRunningEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; @@ -186,16 +185,14 @@ public class QueueFragment extends Fragment implements MaterialToolbar.OnMenuIte } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with DownloadEvent"); - DownloaderUpdate update = event.update; - refreshToolbarState(); - if (recyclerAdapter != null && update.mediaIds.length > 0) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(queue, mediaId); - if (pos >= 0) { - recyclerAdapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + if (queue == null) { + return; + } + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(queue, downloadUrl); + if (pos >= 0) { + recyclerAdapter.notifyItemChangedCompat(pos); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java index d2aa35549..b85e34e7d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java @@ -28,9 +28,8 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; import de.danoeh.antennapod.adapter.HorizontalFeedListAdapter; -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.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; @@ -295,15 +294,14 @@ public class SearchFragment extends Fragment { } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - DownloaderUpdate update = event.update; - if (adapter != null && update.mediaIds.length > 0) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(results, mediaId); - if (pos >= 0) { - adapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + if (results == null) { + return; + } + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(results, downloadUrl); + if (pos >= 0) { + adapter.notifyItemChangedCompat(pos); } } } 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 490c79d47..a6daec2e7 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -36,7 +36,6 @@ 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.core.menuhandler.MenuItemUtils; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.NavDrawerData; @@ -362,12 +361,6 @@ public class SubscriptionFragment extends Fragment loadSubscriptions(); } - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - refreshToolbarState(); - } - @Override public void onEndSelectMode() { speedDialView.close(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java b/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java index e076d35b6..a14bfcd16 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java @@ -6,13 +6,10 @@ import androidx.annotation.PluralsRes; import com.google.android.material.snackbar.Snackbar; -import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.LongList; @@ -93,14 +90,12 @@ public class EpisodeMultiSelectActionHandler { private void downloadChecked(List<FeedItem> items) { // download the check episodes in the same order as they are currently displayed - List<DownloadRequest> requests = new ArrayList<>(); for (FeedItem episode : items) { if (episode.hasMedia() && !episode.getFeed().isLocalFeed()) { - requests.add(DownloadRequestCreator.create(episode.getMedia()).build()); + DownloadServiceInterface.get().download(activity, episode); } } - DownloadServiceInterface.get().download(activity, true, requests.toArray(new DownloadRequest[0])); - showMessage(R.plurals.downloading_batch_label, requests.size()); + showMessage(R.plurals.downloading_batch_label, items.size()); } private void deleteChecked(List<FeedItem> items) { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadsPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadsPreferencesFragment.java index c486089fc..7b0c3efdf 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadsPreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadsPreferencesFragment.java @@ -1,7 +1,6 @@ package de.danoeh.antennapod.fragment.preferences; import android.content.SharedPreferences; -import android.content.res.Resources; import android.os.Bundle; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; @@ -43,7 +42,6 @@ public class DownloadsPreferencesFragment extends PreferenceFragmentCompat @Override public void onResume() { super.onResume(); - setParallelDownloadsText(UserPreferences.getParallelDownloads()); setDataFolderText(); } @@ -52,12 +50,6 @@ public class DownloadsPreferencesFragment extends PreferenceFragmentCompat ((PreferenceActivity) getActivity()).openScreen(R.xml.preferences_autodownload); 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()); @@ -73,12 +65,6 @@ public class DownloadsPreferencesFragment extends PreferenceFragmentCompat }); } - private void setParallelDownloadsText(int downloads) { - final Resources res = getActivity().getResources(); - String s = res.getString(R.string.parallel_downloads, downloads); - findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS).setSummary(s); - } - private void setDataFolderText() { File f = UserPreferences.getDataFolder(null); if (f != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java deleted file mode 100644 index a15c6d6b2..000000000 --- a/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java +++ /dev/null @@ -1,108 +0,0 @@ -package de.danoeh.antennapod.preferences; - -import android.content.Context; -import androidx.appcompat.app.AlertDialog; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import androidx.preference.Preference; -import android.text.InputFilter; -import android.util.AttributeSet; -import android.view.View; -import android.view.WindowManager; -import android.widget.EditText; - -import de.danoeh.antennapod.R; - -public class NumberPickerPreference extends Preference { - private Context context; - private int defaultValue = 0; - private int minValue = 0; - private int maxValue = Integer.MAX_VALUE; - - public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(context, attrs); - } - - public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - public NumberPickerPreference(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public NumberPickerPreference(Context context) { - super(context); - this.context = context; - } - - private void init(Context context, AttributeSet attrs) { - this.context = context; - - for (int i = 0; i < attrs.getAttributeCount(); i++) { - String name = attrs.getAttributeName(i); - String value = attrs.getAttributeValue(i); - switch (name) { - case "defaultValue": - defaultValue = Integer.parseInt(value); - break; - case "minValue": - minValue = Integer.parseInt(value); - break; - case "maxValue": - maxValue = Integer.parseInt(value); - break; - } - } - } - - @Override - protected void onClick() { - super.onClick(); - - View view = View.inflate(context, R.layout.numberpicker, null); - EditText number = view.findViewById(R.id.number); - number.setText(getSharedPreferences().getString(getKey(), ""+defaultValue)); - number.setFilters(new InputFilter[]{(source, start, end, dest, dstart, dend) -> { - try { - String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend); - newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart); - int input = Integer.parseInt(newVal); - if (input >= minValue && input <= maxValue) { - return null; - } - } catch (NumberFormatException nfe) { - nfe.printStackTrace(); - } - return ""; - }}); - - AlertDialog dialog = new MaterialAlertDialogBuilder(context) - .setTitle(getTitle()) - .setView(view) - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { - try { - String numberString = number.getText().toString(); - int value = Integer.parseInt(numberString); - - if (value < minValue || value > maxValue) { - return; - } - - getSharedPreferences().edit().putString(getKey(), "" + value).apply(); - - if (getOnPreferenceChangeListener() != null) { - getOnPreferenceChangeListener().onPreferenceChange(this, value); - } - } catch (NumberFormatException e) { - // Do not set value - } - }) - .create(); - dialog.show(); - dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EpisodesSurpriseSection.java b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EpisodesSurpriseSection.java index 7e2c855e9..298bd05c5 100644 --- a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EpisodesSurpriseSection.java +++ b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/EpisodesSurpriseSection.java @@ -13,11 +13,10 @@ import androidx.recyclerview.widget.RecyclerView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.HorizontalItemListAdapter; -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.storage.DBReader; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; @@ -32,6 +31,7 @@ import io.reactivex.schedulers.Schedulers; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -41,7 +41,7 @@ public class EpisodesSurpriseSection extends HomeSection { private static int seed = 0; private HorizontalItemListAdapter listAdapter; private Disposable disposable; - private List<FeedItem> episodes; + private List<FeedItem> episodes = new ArrayList<>(); @Nullable @Override @@ -103,9 +103,6 @@ public class EpisodesSurpriseSection extends HomeSection { @Subscribe(threadMode = ThreadMode.MAIN) public void onEventMainThread(FeedItemEvent event) { Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - if (episodes == null) { - return; - } for (int i = 0, size = event.items.size(); i < size; i++) { FeedItem item = event.items.get(i); int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId()); @@ -118,15 +115,11 @@ public class EpisodesSurpriseSection extends HomeSection { } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with DownloadEvent"); - DownloaderUpdate update = event.update; - if (listAdapter != null && update.mediaIds.length > 0) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId); - if (pos >= 0) { - listAdapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(episodes, downloadUrl); + if (pos >= 0) { + listAdapter.notifyItemChangedCompat(pos); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/InboxSection.java b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/InboxSection.java index 8d343a16a..fe9d15dc1 100644 --- a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/InboxSection.java +++ b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/InboxSection.java @@ -14,11 +14,10 @@ import androidx.recyclerview.widget.RecyclerView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; -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.storage.DBReader; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; @@ -35,6 +34,7 @@ import io.reactivex.schedulers.Schedulers; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -42,7 +42,7 @@ public class InboxSection extends HomeSection { public static final String TAG = "InboxSection"; private static final int NUM_EPISODES = 2; private EpisodeItemListAdapter adapter; - private List<FeedItem> items; + private List<FeedItem> items = new ArrayList<>(); private Disposable disposable; @Nullable @@ -97,15 +97,11 @@ public class InboxSection extends HomeSection { } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with DownloadEvent"); - DownloaderUpdate update = event.update; - if (adapter != null && update.mediaIds.length > 0) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(items, mediaId); - if (pos >= 0) { - adapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(items, downloadUrl); + if (pos >= 0) { + adapter.notifyItemChangedCompat(pos); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/QueueSection.java b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/QueueSection.java index 070d56ed6..33335f2bb 100644 --- a/app/src/main/java/de/danoeh/antennapod/ui/home/sections/QueueSection.java +++ b/app/src/main/java/de/danoeh/antennapod/ui/home/sections/QueueSection.java @@ -13,11 +13,10 @@ import androidx.recyclerview.widget.RecyclerView; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.HorizontalItemListAdapter; -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.storage.DBReader; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.event.EpisodeDownloadEvent; import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.QueueEvent; @@ -33,6 +32,7 @@ import io.reactivex.schedulers.Schedulers; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import java.util.ArrayList; import java.util.List; public class QueueSection extends HomeSection { @@ -40,7 +40,7 @@ public class QueueSection extends HomeSection { private static final int NUM_EPISODES = 8; private HorizontalItemListAdapter listAdapter; private Disposable disposable; - private List<FeedItem> queue; + private List<FeedItem> queue = new ArrayList<>(); @Nullable @Override @@ -102,15 +102,11 @@ public class QueueSection extends HomeSection { } @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with DownloadEvent"); - DownloaderUpdate update = event.update; - if (listAdapter != null && update.mediaIds.length > 0) { - for (long mediaId : update.mediaIds) { - int pos = FeedItemUtil.indexOfItemWithMediaId(queue, mediaId); - if (pos >= 0) { - listAdapter.notifyItemChangedCompat(pos); - } + public void onEventMainThread(EpisodeDownloadEvent event) { + for (String downloadUrl : event.getUrls()) { + int pos = FeedItemUtil.indexOfItemWithDownloadUrl(queue, downloadUrl); + if (pos >= 0) { + listAdapter.notifyItemChangedCompat(pos); } } } diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java index fd3ec9299..03df844b1 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java +++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java @@ -21,8 +21,6 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.CoverLoader; import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.util.PlaybackStatus; import de.danoeh.antennapod.core.util.download.MediaSizeLoader; import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; @@ -31,6 +29,7 @@ import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.model.playback.MediaType; import de.danoeh.antennapod.core.feed.util.ImageResourceUtils; +import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -117,6 +116,7 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder { bind(item.getMedia()); } else { secondaryActionProgress.setPercentage(0, item); + secondaryActionProgress.setIndeterminate(false); isVideo.setVisibility(View.GONE); progressBar.setVisibility(View.GONE); duration.setVisibility(View.GONE); @@ -145,14 +145,17 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder { itemView.setBackgroundResource(ThemeUtils.getDrawableFromAttr(activity, R.attr.selectableItemBackground)); } - if (DownloadService.isDownloadingFile(media.getDownload_url())) { - final DownloadRequest downloadRequest = DownloadService.findRequest(media.getDownload_url()); - float percent = 0.01f * downloadRequest.getProgressPercent(); + if (DownloadServiceInterface.get().isDownloadingEpisode(media.getDownload_url())) { + float percent = 0.01f * DownloadServiceInterface.get().getProgress(media.getDownload_url()); secondaryActionProgress.setPercentage(Math.max(percent, 0.01f), item); + secondaryActionProgress.setIndeterminate( + DownloadServiceInterface.get().isEpisodeQueued(media.getDownload_url())); } else if (media.isDownloaded()) { secondaryActionProgress.setPercentage(1, item); // Do not animate 100% -> 0% + secondaryActionProgress.setIndeterminate(false); } else { secondaryActionProgress.setPercentage(0, item); // Animate X% -> 0% + secondaryActionProgress.setIndeterminate(false); } duration.setText(Converter.getDurationStringLong(media.getDuration())); @@ -210,6 +213,7 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder { pubDate.setText("████"); duration.setText("████"); secondaryActionProgress.setPercentage(0, null); + secondaryActionProgress.setIndeterminate(false); progressBar.setVisibility(View.GONE); position.setVisibility(View.GONE); dragHandle.setVisibility(View.GONE); diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/HorizontalItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/HorizontalItemViewHolder.java index 05240b371..f809de175 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/viewholder/HorizontalItemViewHolder.java +++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/HorizontalItemViewHolder.java @@ -14,13 +14,12 @@ import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.CoverLoader; import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton; import de.danoeh.antennapod.core.feed.util.ImageResourceUtils; -import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.util.DateFormatter; import de.danoeh.antennapod.core.util.PlaybackStatus; import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; +import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface; import de.danoeh.antennapod.ui.common.CircularProgressBar; import de.danoeh.antennapod.ui.common.SquareImageView; import de.danoeh.antennapod.ui.common.ThemeUtils; @@ -85,14 +84,17 @@ public class HorizontalItemViewHolder extends RecyclerView.ViewHolder { setProgressBar(false, 0); } - if (DownloadService.isDownloadingFile(media.getDownload_url())) { - final DownloadRequest downloadRequest = DownloadService.findRequest(media.getDownload_url()); - float percent = 0.01f * downloadRequest.getProgressPercent(); + if (DownloadServiceInterface.get().isDownloadingEpisode(media.getDownload_url())) { + float percent = 0.01f * DownloadServiceInterface.get().getProgress(media.getDownload_url()); circularProgressBar.setPercentage(Math.max(percent, 0.01f), item); + circularProgressBar.setIndeterminate( + DownloadServiceInterface.get().isEpisodeQueued(media.getDownload_url())); } else if (media.isDownloaded()) { circularProgressBar.setPercentage(1, item); // Do not animate 100% -> 0% + circularProgressBar.setIndeterminate(false); } else { circularProgressBar.setPercentage(0, item); // Animate X% -> 0% + circularProgressBar.setIndeterminate(false); } } } @@ -107,6 +109,7 @@ public class HorizontalItemViewHolder extends RecyclerView.ViewHolder { date.setText("███"); secondaryActionIcon.setImageDrawable(null); circularProgressBar.setPercentage(0, null); + circularProgressBar.setIndeterminate(false); setProgressBar(true, 50); } diff --git a/app/src/main/res/layout/numberpicker.xml b/app/src/main/res/layout/numberpicker.xml deleted file mode 100644 index d493f2e6c..000000000 --- a/app/src/main/res/layout/numberpicker.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - android:padding="16dp"> - - <EditText - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:ems="10" - android:selectAllOnFocus="true" - android:id="@+id/number" /> - -</LinearLayout> diff --git a/app/src/main/res/xml/preferences_downloads.xml b/app/src/main/res/xml/preferences_downloads.xml index 865748d20..18fc7df11 100644 --- a/app/src/main/res/xml/preferences_downloads.xml +++ b/app/src/main/res/xml/preferences_downloads.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:numberpicker="http://schemas.android.com/apk/de.danoeh.antennapod" xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch"> <Preference @@ -56,12 +55,6 @@ android:key="prefMobileUpdateTypes" android:summary="@string/pref_mobileUpdate_sum" android:title="@string/pref_mobileUpdate_title"/> - <de.danoeh.antennapod.preferences.NumberPickerPreference - android:defaultValue="4" - numberpicker:minValue="1" - numberpicker:maxValue="50" - android:key="prefParallelDownloads" - android:title="@string/pref_parallel_downloads_title"/> <Preference android:key="prefProxy" android:summary="@string/pref_proxy_sum" |